﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.IO;
using System.Xml;

namespace SystemHelperLibrary.API
{
	[StructLayout(LayoutKind.Sequential)]
	public struct SYSTEM_INFO
	{
		public uint dwOemId;
		public uint dwPageSize;
		public uint lpMinimumApplicationAddress;
		public uint lpMaximumApplicationAddress;
		public uint dwActiveProcessorMask;
		public uint dwNumberOfProcessors;
		public uint dwProcessorType;
		public uint dwAllocationGranularity;
		public uint dwProcessorLevel;
		public uint dwProcessorRevision;
	}

	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
	public class OpenFileName
	{
		public int lstructSize;
		public int hwndOwner;
		public int hInstance;
		public string lpstrFilter = null;
		public string lpstrCustomFilter = null;
		public int lMaxCustomFilter;
		public int lFilterIndex;
		public string lpstrFile = null;
		public int lMaxFile = 0;
		public string lpstrFiteTitle = null;
		public int lMaxFileTitle = 0;
		public string lpstrInitialDir = null;
		public string lpstrTitle = null;
		public int lFlags;
		public ushort nFileOffset;
		public ushort nFileExtension;
		public string lpstrDefExt = null;
		public int lCustData;
		public int lpfHook;
		public int lpTemplateName;
	}

	public enum BeepTypes
	{
		Simple = -1,
		Ok = 0x00000000,
		IconHand = 0x00000010,
		IconQuestion = 0x00000020,
		IconExclamation = 0x00000030,
		IconAsterisk = 0x00000040
	}

	public class ApiHelper
	{
		public const int MAX_PATH = 260;
		public const int MAX_ALTERNATE = 14;

		public const int SND_FILENAME = 0x00020000;
		public const int SND_ASYNC = 0x0010;//0x0001;

		[Flags()]
		public enum MessageBoxStyle : uint
		{
			MB_OK = 0,
			MB_OKCANCEL = 1,
			MB_RETRYCANCEL = 2,
			MB_YESNO = 4,
			MB_YESNOCANCEL = 8,
			MB_ICONEXCLAMATION = 16,
			MB_ICONWARNING = 32,
			MB_ICONINFORMATION = 64
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct RECT
		{
			public int left;
			public int top;
			public int right;
			public int bottom;
		}

		[DllImport("Kernel32", CharSet = CharSet.Auto)]
		internal static extern bool GetComputerName(StringBuilder buffer, ref uint size);

		[DllImport("kernel32", SetLastError = true)]
		internal static extern IntPtr LoadLibrary(string lpFileName);

		[DllImport("Advapi32.dll")]
		internal static extern bool GetUserName(StringBuilder lpBuffer, ref int nSize);

		[DllImport("User32", CharSet = CharSet.Auto)]
		internal static extern string CharLower(string lpsz);

		[DllImport("User32", CharSet = CharSet.Auto)]
		internal static extern string CharUpper(string lpsz);

		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		internal static extern uint CharLowerBuff([In, Out] StringBuilder lpsz, uint cchLength);

		[DllImport("User32.dll")]
		internal static extern int MessageBox(int hwnd, string message, string caption, int type);

		[DllImport("kernel32.dll", EntryPoint = "GetSystemInfo")]
		internal static extern void GetSystemInfo(ref SYSTEM_INFO pSI);

		[DllImport("User32.dll")]
		internal static extern Boolean MessageBeep(UInt32 beepType);

		[DllImport("winmm.dll")]
		internal static extern bool PlaySound(string pszSound, int hmod, int fdwSound);

		[DllImport("User32.dll")]
		internal static extern Boolean UpdateWindow(int hWnd);

		[DllImport("Kernel32.dll", SetLastError = true)]
		internal static extern Boolean Beep(UInt32 frequency, UInt32 duration);

		[DllImport("Advapi32.dll", CharSet = CharSet.Auto)]
		internal static extern Boolean FileEncryptionStatus(String filename, out UInt32 status);

		[DllImport("Kernel32", CharSet = CharSet.Auto)]
		internal static extern Int32 GetShortPathName(String path, StringBuilder shortPath, Int32 shortPathLength);

		[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
		internal static extern bool GetOpenFileName([In, Out] OpenFileName ofn);

		[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
		internal static extern bool GetSaveFileName([In, Out] OpenFileName ofn);

		[DllImport("user32.dll")]
		internal static extern int GetForegroundWindow();
		[DllImport("User32.dll")]
		internal static extern Int32 SetForegroundWindow(int hWnd);
		[DllImport("User32.dll")]
		internal static extern Boolean EnumChildWindows(int hWndParent, Delegate lpEnumFunc, int lParam);
		[DllImport("user32.dll")]
		internal static extern int GetWindowText(int hWnd, StringBuilder text, int count);
		[DllImport("User32.Dll")]
		internal static extern void SetWindowText(IntPtr hwnd, String lpString);
		[DllImport("User32.dll")]
		internal static extern Int32 GetWindowTextLength(int hwnd);

		[DllImport("User32.dll")]
		internal static extern Int32 FindWindow(String lpClassName, String lpWindowName);

		[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
		internal static extern int GetDesktopWindow();

		[DllImport("user32.dll")]
		internal static extern int GetClassName(IntPtr hwnd, [MarshalAs(UnmanagedType.LPStr)] StringBuilder buf,
												 int nMaxCount);
		[DllImport("user32.dll")]
		internal static extern int GetWindowRect(IntPtr hwnd, ref RECT rc);

		internal delegate bool EnumWindowsCB(int hwnd, int lparam);

		[DllImport("user32")]
		internal static extern int EnumWindows(EnumWindowsCB cb, int lparam);

		[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
		internal static extern int GetCursorPos(ref POINTL lpPoint);

		[StructLayout(LayoutKind.Sequential)]
		public class POINTL
		{
			public int x;
			public int y;
		}

		[DllImport("kernel32", SetLastError = true)]
		internal static extern bool GetVersionEx(ref OSVERSIONINFOEX osvi);

		[StructLayout(LayoutKind.Sequential)]
		public struct OSVERSIONINFOEX
		{
			public uint dwOSVersionInfoSize;
			public uint dwMajorVersion;
			public uint dwMinorVersion;
			public uint dwBuildNumber;
			public uint dwPlatformId;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
			public string szCSDVersion;
			public UInt16 wServicePackMajor;
			public UInt16 wServicePackMinor;
			public UInt16 wSuiteMask;
			public byte wProductType;
			public byte wReserved;
		}

		[DllImport("kernel32.dll", SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool CloseHandle(IntPtr hObject);

		[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool CopyFile(string lpExistingFileName, string lpNewFileName, bool bFailIfExists);

		[DllImport("kernel32.dll")]
		internal static extern bool DeleteFile(string filename);
		[DllImport("kernel32.dll")]
		internal static extern bool FlushFileBuffers(IntPtr hFile);

		[StructLayout(LayoutKind.Sequential)]
		public struct FILETIME
		{
			public uint dwLowDateTime;
			public uint dwHighDateTime;
		};

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		public struct WIN32_FIND_DATA
		{
			public System.IO.FileAttributes dwFileAttributes;
			public FILETIME ftCreationTime;
			public FILETIME ftLastAccessTime;
			public FILETIME ftLastWriteTime;
			public uint nFileSizeHigh; //changed all to uint from int, otherwise you run into unexpected overflow
			public uint nFileSizeLow;  //| http://www.pinvoke.net/default.aspx/Structures/WIN32_FIND_DATA.html
			public uint dwReserved0;   //|
			public uint dwReserved1;   //v
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
			public string cFileName;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ALTERNATE)]
			public string cAlternate;
		}

		[DllImport("kernel32", CharSet = CharSet.Unicode)]
		internal static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
		[DllImport("kernel32", CharSet = CharSet.Unicode)]
		internal static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
		[DllImport("kernel32.dll")]
		internal static extern bool FindClose(IntPtr hFindFile);

		private long RecurseDirectory(string directory, int level, out int files, out int folders)
		{
			IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
			long size = 0;
			files = 0;
			folders = 0;

			WIN32_FIND_DATA findData;

			IntPtr findHandle;

			// please note that the following line won't work if you try this on a network folder, like \\Machine\C$
			// simply remove the \\?\ part in this case or use \\?\UNC\ prefix
			findHandle = FindFirstFile(@"\\?\" + directory + @"\*", out findData);
			if (findHandle != INVALID_HANDLE_VALUE)
			{
				do
				{
					if ((findData.dwFileAttributes & System.IO.FileAttributes.Directory) != 0)
					{
						if (findData.cFileName != "." && findData.cFileName != "..")
						{
							folders++;
							int subfiles, subfolders;
							string subdirectory = directory + (directory.EndsWith(@"\") ? "" : @"\") +
								findData.cFileName;
							if (level != 0)  // allows -1 to do complete search.
							{
								size += RecurseDirectory(subdirectory, level - 1, out subfiles, out subfolders);

								folders += subfolders;
								files += subfiles;
							}
						}
					}
					else
					{
						// File
						files++;
						size += (long)findData.nFileSizeLow + (long)findData.nFileSizeHigh * 4294967296;
					}
				}
				while (FindNextFile(findHandle, out findData));
				FindClose(findHandle);
			}
			return size;
		}

		#region Copy file Ex

		[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
		[return: MarshalAs(UnmanagedType.Bool)]
		static extern bool CopyFileEx(string lpExistingFileName, string lpNewFileName,
										CopyProgressRoutine lpProgressRoutine, IntPtr lpData, ref Int32 pbCancel,
										CopyFileFlags dwCopyFlags);

		internal delegate CopyProgressResult CopyProgressRoutine(long TotalFileSize, long TotalBytesTransferred, long StreamSize,
											long StreamBytesTransferred, uint dwStreamNumber, CopyProgressCallbackReason dwCallbackReason,
											IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData);

		int pbCancel;

		public enum CopyProgressResult : uint
		{
			PROGRESS_CONTINUE = 0,
			PROGRESS_CANCEL = 1,
			PROGRESS_STOP = 2,
			PROGRESS_QUIET = 3
		}

		public enum CopyProgressCallbackReason : uint
		{
			CALLBACK_CHUNK_FINISHED = 0x00000000,
			CALLBACK_STREAM_SWITCH = 0x00000001
		}

		[Flags]
		public enum CopyFileFlags : uint
		{
			COPY_FILE_FAIL_IF_EXISTS = 0x00000001,
			COPY_FILE_RESTARTABLE = 0x00000002,
			COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x00000004,
			COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x00000008
		}

		public void XCopy(string oldFile, string newFile)
		{
			CopyFileEx(oldFile, newFile, new CopyProgressRoutine(this.CopyProgressHandler), IntPtr.Zero, ref pbCancel, CopyFileFlags.COPY_FILE_RESTARTABLE);
		}

		private CopyProgressResult CopyProgressHandler(long total, long transferred, long streamSize, long StreamByteTrans,
			uint dwStreamNumber, CopyProgressCallbackReason reason, IntPtr hSourceFile, IntPtr hDestinationFile, IntPtr lpData)
		{
			return CopyProgressResult.PROGRESS_CONTINUE;
		}

		#endregion

		public static void ShowMessageBox(int hwnd, string message, string caption)
		{
			MessageBox(hwnd, message, caption, 0);
		}

		/// <summary>
		/// Message beep signal
		/// </summary>
		/// <exception cref="System.ComponentModel.Win32Exception"></exception>
		/// <param name="type">Beep type</param>
		public static void MessageBeepApi(BeepTypes type)
		{
			if (!MessageBeep((UInt32)type))
			{
				Int32 err = Marshal.GetLastWin32Error();
				throw new Win32Exception(err);
			}
		}

		public static SYSTEM_INFO GetSystemInfos()
		{
			SYSTEM_INFO sys = new SYSTEM_INFO();
			GetSystemInfo(ref sys);
			return sys;
		}

		public static void GetOpenFileNameApi(OpenFileName ofn)
		{
			if (GetOpenFileName(ofn))
			{
				int handle = ofn.hInstance;

			}
		}

		public static void GetSaveFileNameApi(OpenFileName ofn)
		{
			if (GetSaveFileName(ofn))
			{
				int handle = ofn.hInstance;
			}
		}

		public static string GetActiveWindowText()
		{
			const int nChars = 256;
			int handle = 0;
			StringBuilder Buff = new StringBuilder(nChars);
			handle = GetForegroundWindow();

			if (GetWindowText(handle, Buff, nChars) > 0)
			{
				return Buff.ToString();
			}

			return string.Empty;
		}

		public static string GetWindowTextApi(Int32 handle)
		{
			const int nChars = 256;
			StringBuilder Buff = new StringBuilder(nChars);
			if (GetWindowText(handle, Buff, nChars) > 0)
			{
				return Buff.ToString();
			}
			return string.Empty;
		}

		public delegate int Callback(int hWnd, int lParam);

		public void SomeMethod()
		{
			int hWnd;
			Callback myCallBack = new Callback(EnumChildGetValue);
			hWnd = FindWindow(null, "CallingWindow");
			if (hWnd == 0)
			{
				System.Windows.MessageBox.Show("Please Start Calling Window Application");
			}
			else
			{
				EnumChildWindows(hWnd, myCallBack, 0);
			}
		}

		public int EnumChildGetValue(int hWnd, int lParam)
		{
			StringBuilder formDetails = new StringBuilder(256);
			int txtValue;
			string editText = "";
			txtValue = GetWindowText(hWnd, formDetails, 256);
			editText = formDetails.ToString().Trim();
			System.Windows.MessageBox.Show(string.Format("Contains text of contro: {0}", editText));
			return 1;
		}

		public static POINTL GetCursorPosition()
		{
			POINTL p = new POINTL();
			GetCursorPos(ref p);
			return p;
		}

		public static OSVERSIONINFOEX GetOsVersion()
		{
			OSVERSIONINFOEX osVersionInfo = new OSVERSIONINFOEX();
			osVersionInfo.dwOSVersionInfoSize = (uint)Marshal.SizeOf(osVersionInfo); // don't forget this line, please!
			GetVersionEx(ref osVersionInfo);
			return osVersionInfo;
		}

		/// <summary>
		/// Close opened handle
		/// </summary>
		/// <exception cref="System.ComponentModel.Win32Exception">Occurs when cannot close handle</exception>
		/// <param name="handle"></param>
		public static void CloseHandleApi(IntPtr handle)
		{
			if (!CloseHandle(handle))
			{
				Int32 err = Marshal.GetLastWin32Error();
				throw new Win32Exception(err);
			}
		}

		public static bool CopyFileApi(string source, string destfile, bool failIfExist)
		{
			return CopyFile(source, destfile, failIfExist);
		}

		public static bool DeleteFileApi(string filename)
		{
			if (string.IsNullOrEmpty(filename))
				return false;

			return DeleteFile(filename);
		}

		public static string CharLowerApi(string data)
		{
			return CharLower(data);
		}

		public static string CharUpperApi(string data)
		{
			return CharUpper(data);
		}

		public static bool IsLibraryExist(string name)
		{
			return !(LoadLibrary(name) == IntPtr.Zero);
		}

		public static string GetUserNameApi()
		{
			StringBuilder Buffer = new StringBuilder(64);
			int nSize = 64;
			GetUserName(Buffer, ref nSize);
			return Buffer.ToString();

		}

		public static void PlaySoundApi(string filename)
		{
			PlaySound(filename, 0, SND_FILENAME | SND_ASYNC);
		}

		public static IntPtr FindWindowApi(string windowName)
		{
			IntPtr wPtr = IntPtr.Zero;
			wPtr = new IntPtr(FindWindow(null, windowName));
			return wPtr;
		}

	}

	public sealed class ShellBin
	{
		private ShellBin() { }

		// No dialog box confirming the deletion of the objects will be displayed.
		public const int SHERB_NOCONFIRMATION = 0x00000001;
		// No dialog box indicating the progress will be displayed.
		public const int SHERB_NOPROGRESSUI = 0x00000002;
		// No sound will be played when the operation is complete.
		public const int SHERB_NOSOUND = 0x00000004;

		[StructLayout(LayoutKind.Sequential, Pack = 4)]
		public struct SHQUERYRBINFO
		{
			public int cbSize;
			public long i64Size;
			public long i64NumItems;
		}

		[DllImport("shell32.dll")]
		internal static extern int SHEmptyRecycleBin(IntPtr hWnd, string pszRootPath, uint dwFlags);
		[DllImport("shell32.dll")]
		internal static extern int SHQueryRecycleBin(string pszRootPath, ref SHQUERYRBINFO pSHQueryRBInfo);

		public static void EmptyRecycleBin()
		{
			ShellBin.EmptyRecycleBin(string.Empty);
		}

		public static void EmptyRecycleBin(string rootPath)
		{
			int hresult = SHEmptyRecycleBin(IntPtr.Zero, rootPath, SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI | SHERB_NOSOUND);
		}

		public static int GetCount()
		{
			SHQUERYRBINFO sqrbi = new SHQUERYRBINFO();
			sqrbi.cbSize = Marshal.SizeOf(typeof(SHQUERYRBINFO));
			int hresult = SHQueryRecycleBin(string.Empty, ref sqrbi);
			return (int)sqrbi.i64NumItems;
		}

		public static int GetCount(string drive)
		{
			SHQUERYRBINFO sqrbi = new SHQUERYRBINFO();
			sqrbi.cbSize = Marshal.SizeOf(typeof(SHQUERYRBINFO));
			int hresult = SHQueryRecycleBin(drive, ref sqrbi);
			return (int)sqrbi.i64NumItems;
		}
	}

	public sealed class WindowsPowerManagement
	{
		private WindowsPowerManagement() { }

		internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
		internal const int TOKEN_QUERY = 0x00000008;
		internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
		internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
		internal const int EWX_LOGOFF = 0x00000000;
		internal const int EWX_SHUTDOWN = 0x00000001;
		internal const int EWX_REBOOT = 0x00000002;
		internal const int EWX_FORCE = 0x00000004;
		internal const int EWX_POWEROFF = 0x00000008;
		internal const int EWX_FORCEIFHUNG = 0x00000010;

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		internal struct TokPriv1Luid
		{
			public int Count;
			public long Luid;
			public int Attr;
		}

		[DllImport("kernel32.dll", ExactSpelling = true)]
		internal static extern IntPtr GetCurrentProcess();

		[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
		internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

		[DllImport("advapi32.dll", SetLastError = true)]
		internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

		[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
		internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len,
															IntPtr prev, IntPtr relen);

		[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
		internal static extern bool ExitWindowsEx(int flg, int rea);

		[DllImport("user32.dll")]
		internal static extern void LockWorkStation();

		private static void DoExitWin(int flg)
		{
			bool ok;
			TokPriv1Luid tp;
			IntPtr hproc = GetCurrentProcess();
			IntPtr htok = IntPtr.Zero;
			ok = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
			tp.Count = 1;
			tp.Luid = 0;
			tp.Attr = SE_PRIVILEGE_ENABLED;
			ok = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
			ok = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
			ok = ExitWindowsEx(flg, 0);
		}

		public static void ShutDownComputer()
		{
			DoExitWin(EWX_SHUTDOWN);
		}

		public static void RestartComputer()
		{
			DoExitWin(EWX_REBOOT);
		}

		public static void LogOff()
		{
			DoExitWin(EWX_LOGOFF);
		}

		public static void PowerOff()
		{
			DoExitWin(EWX_POWEROFF);
		}

		public static void Reboot()
		{
			ExitWindowsEx(2, 0);
		}

		public static void LockWorkStationApi()
		{
			LockWorkStation();
		}
	}

	public static class TaskBarHelper
	{
		private static string StartMenuCaption = string.Empty;
		private static IntPtr vistaStartMenuWnd = IntPtr.Zero;
		private delegate bool EnumThreadProc(IntPtr hwnd, IntPtr lParam);


		static TaskBarHelper()
		{
			string name = System.Threading.Thread.CurrentThread.CurrentCulture.Name;
			StartMenuCaption = name.ToLower().Contains("ru") ? "Пуск" : "Start";
		}

		[DllImport("user32.dll")]
		static extern uint GetWindowThreadProcessId(IntPtr hwnd, out int lpdwProcessId);

		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		private static extern bool EnumThreadWindows(int threadId, EnumThreadProc pfnEnum, IntPtr lParam);

		[DllImport("user32.dll")]
		private static extern IntPtr FindWindow(string ClassName, string WindowName);

		[DllImport("user32.dll")]
		private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string windowName);

		[DllImport("user32.dll")]
		private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

		[DllImport("user32.dll")]
		private static extern int GetWindowText(int hWnd, StringBuilder text, int count);

		const int SW_HIDE = 0;
		const int SW_SHOW = 5;

		private static bool show = false;
		private static int procId = 0;

		public static int ProcessId
		{
			get { return procId; }
			set { procId = value; }
		}

		public static void SetProcessId(int id)
		{
			procId = id;
		}

		public static void HideTaskBar()
		{
			// Получим дескриптор панели задач
			IntPtr taskBarWnd = FindWindow("Shell_TrayWnd", null);
			// Получим дескриптор кнопки ПУСК
			IntPtr startWnd = FindWindow("Button", null);

			// Прячем/показываем панель задач
			if (taskBarWnd != IntPtr.Zero)
			{
				ShowWindow(taskBarWnd, show ? SW_SHOW : SW_HIDE);
			}
			// Прячем/показываем кнопку ПУСК
			if (startWnd != IntPtr.Zero)
			{
				ShowWindow(startWnd, show ? SW_SHOW : SW_HIDE);
			}
			show = !show;
		}


		public static void Hide()
		{
			// Описатель панели задач
			IntPtr taskBarWnd = FindWindow("Shell_TrayWnd", null);
			//ShowWindow(taskBarWnd, SW_HIDE);

			// Описатель области уведомлений
			IntPtr tray = FindWindowEx(taskBarWnd, IntPtr.Zero, "TrayNotifyWnd", null);

			// Прячем область уведомлений
			// ShowWindow(tray, SW_HIDE);

			// Описатель системных часов
			IntPtr trayclock = FindWindowEx(tray, IntPtr.Zero, "TrayClockWClass", null);
			// Прячем системные часы
			ShowWindow(trayclock, SW_HIDE);

		}

		public static void EnumerateWindows()
		{
			System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(procId);
			if (p != null)
			{
				// enumerate all threads of that process...
				foreach (System.Diagnostics.ProcessThread t in p.Threads)
				{
					EnumThreadWindows(t.Id, MyEnumThreadWindowsProc, IntPtr.Zero);
				}
			}
		}

		private static bool MyEnumThreadWindowsProc(IntPtr hWnd, IntPtr lParam)
		{
			StringBuilder buffer = new StringBuilder(256);
			if (GetWindowText(hWnd.ToInt32(), buffer, buffer.Capacity) > 0)
			{
				if (buffer.ToString() == StartMenuCaption)
				{
					vistaStartMenuWnd = hWnd;
					return false;
				}
			}
			return true;
		}

	}

	public static class ArchitectureHelper
	{
		[DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
		public extern static IntPtr LoadLibrary(string libraryName);
		[DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
		public extern static IntPtr GetProcAddress(IntPtr hwnd, string procedureName);

		private delegate bool IsWow64ProcessDelegate([In] IntPtr handle, [Out] out bool isWow64Process);

		public static bool IsOS64Bit()
		{
			if (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor()))
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		private static IsWow64ProcessDelegate GetIsWow64ProcessDelegate()
		{
			IntPtr handle = LoadLibrary("kernel32");
			if (handle != IntPtr.Zero)
			{
				IntPtr fnPtr = GetProcAddress(handle, "IsWow64Process");
				if (fnPtr != IntPtr.Zero)
				{
					return (IsWow64ProcessDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)fnPtr, typeof(IsWow64ProcessDelegate));
				}
			}
			return null;
		}
		private static bool Is32BitProcessOn64BitProcessor()
		{
			IsWow64ProcessDelegate fnDelegate = GetIsWow64ProcessDelegate();
			if (fnDelegate == null)
			{
				return false;
			}
			bool isWow64;
			bool retVal = fnDelegate.Invoke(System.Diagnostics.Process.GetCurrentProcess().Handle, out isWow64);
			if (retVal == false)
			{
				return false;
			}
			return isWow64;
		}
	}

	public sealed class ComGuid
	{
		[DllImport("ole32.dll", SetLastError = true)]
		private static extern int CoCreateGuid(ref Guid pguid);

		private ComGuid()
		{ }

		public static Guid NewGuid()
		{
			Guid val = Guid.Empty;
			int hresult = 0; hresult = CoCreateGuid(ref val);

			if (hresult != 0)
			{
				throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error(), "Error creating new Guid");
			}
			return val;
		}
	}

	public sealed class KeyboardHelper
	{
		[DllImport("User32.dll")]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool GetKeyboardState(byte[] lpKeyState);

		public static int GetKeyState()
		{
			byte[] keys = new byte[256];
			//Get pressed keys
			if (!GetKeyboardState(keys))
			{
				throw new Win32Exception(Marshal.GetLastWin32Error());
			}

			for (int i = 0; i < 256; i++)
			{
				byte key = keys[i];
				//Logical 'and' so we can drop the low-order bit for toggled keys, else that key will appear with the value 1!
				if ((key & 0x80) != 0)
				{
					//This is just for a short demo, you may want this to return multiple keys!
					return (int)key;
				}
			}
			return -1;
		}

	}

	public sealed class WindowHelper
	{
		public const Int32 WM_SYSCOMMAND = 0x112;
		public const Int32 SC_SCREENSAVE = 0xF140;
		public const int AW_SLIDE = 0X40000;
		public const int AW_ACTIVATE = 0X20000;
		public const int AW_BLEND = 0X80000;
		public const int AW_HIDE = 0X10000; //Скрытие окна. По умолчанию окно видимо 
		public const int AW_VER_NEGATIVE = 0x00000008;// Анимация окна снизу вверх. Флаг игнорируется при использовании AW_CENTER или AW_BLEND 

		[StructLayout(LayoutKind.Sequential)]
		internal struct MSG
		{
			public IntPtr hwnd;
			UInt32 SendMessage;
			IntPtr wParam;
			IntPtr lParam;
			uint time;
			POINT point;
		}

		[StructLayout(LayoutKind.Sequential)]
		internal struct POINT
		{
			public int x;
			public int y;
		}

		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		internal static extern int AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags);

		[DllImport("dwmapi.dll", PreserveSig = false)]
		internal static extern bool DwmIsCompositionEnabled();

		[DllImport("dwmapi.dll", PreserveSig = false)]
		internal static extern void DwmEnableComposition(bool bEnable);

		[DllImport("user32.dll", CharSet = CharSet.Auto)]
		internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
		[DllImport("user32.dll")]
		internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);

		[DllImport("user32.dll")]
		internal static extern int GetMessageTime();
		[DllImport("user32.dll")]
		internal static extern void PostQuitMessage(int exitCode);

		[DllImport("user32.dll")]
		internal static extern bool DestroyWindow(IntPtr hwnd);

		[DllImport("user32.dll")]
		internal static extern bool CloseWindow(IntPtr hwnd);

		[DllImport("user32.dll")]
		internal static extern bool EnableWindow(IntPtr hwnd, bool isEnable);

		[DllImport("user32.dll")]
		internal static extern IntPtr GetActiveWindow();

		[DllImport("user32.dll")]
		internal static extern IntPtr GetDesktopWindow();

		[DllImport("user32.dll")]
		internal static extern IntPtr GetFocus();

		[DllImport("user32.dll")]
		internal static extern IntPtr GetForegroundWindow();

		[DllImport("user32.dll")]
		internal static extern IntPtr GetParent(IntPtr hwnd);

		[DllImport("user32.dll")]
		internal static extern bool IsZoomed(IntPtr hwnd);

		[DllImport("user32.dll")]
		internal static extern bool ExitWindows(uint dwReserved, uint uReserved);

		public static void TurnScreensaverOnOrOff(bool status)
		{
			SendMessage(IntPtr.Zero, WM_SYSCOMMAND, SC_SCREENSAVE, status == true ? 0 : 1);
		}

		public static bool DestroyWindowApi(IntPtr hwnd)
		{
			return DestroyWindow(hwnd);
		}

		public static bool CloseWindowApi(IntPtr hwnd)
		{
			return CloseWindow(hwnd);
		}

		public static bool EnableWindowApi(IntPtr hwnd, bool isEnable)
		{
			return EnableWindow(hwnd, isEnable);
		}

		public static IntPtr GetActiveWindowApi()
		{
			return GetActiveWindow();
		}

		public static IntPtr GetDesktopWindowApi()
		{
			return GetDesktopWindow();
		}

		public static IntPtr GetFocusApi()
		{
			return GetFocus();
		}

		public static IntPtr GetForegroundWindowApi()
		{
			return GetForegroundWindow();
		}

		public static IntPtr GetParentApi(IntPtr hwnd)
		{
			return GetParent(hwnd);
		}

		public static bool IsZoomedApi(IntPtr hwnd)
		{
			return IsZoomed(hwnd);
		}

		public static bool ExitWindowsApi()
		{
			return ExitWindows(0, 0);
		}
	}

	public sealed class WlanHelper : IDisposable
	{
		/// <summary>
		/// Windows Vista\7 WiFi API Version
		/// </summary>
		internal const int WLAN_API_VERSION_2_0 = 2;
		/// <summary>
		/// Windows XP Sp2 API Version
		/// </summary>
		internal const int WLAN_API_VERSION_1_0 = 1;
		/// <summary>
		/// No erorr, success operation
		/// </summary>
		internal const int ERROR_SUCCESS = 0;
		internal const int ERROR_ACCESS_DENIED = 5;
		internal const int ERROR_INVALID_HANDLE = 6;
		internal const int ERROR_NOT_ENOUGH_MEMORY = 8;
		internal const int ERROR_NOT_SUPPORTED = 50;
		internal const int ERROR_NETWORK_ACCESS_DENIED = 65;
		internal const int ERROR_INVALID_PARAMETER = 87;

		#region WlanHelper Events

		public event EventHandler HostedNetworkStarted;
		public event EventHandler HostedNetworkStopped;
		public event EventHandler HostedNetworkAvailable;

		public event EventHandler StationJoin;
		public event EventHandler StationLeave;
		public event EventHandler StationStateChange;

		#endregion

		private IntPtr WlanHandle;
		private uint WlanVersion;
		private IntPtr ppInterfaceList = IntPtr.Zero;
		private WLAN_INTERFACE_INFO_LIST interfaceList;
		private WLAN_NOTIFICATION_CALLBACK m_notifyCallback;
		private WLAN_HOSTED_NETWORK_STATE m_HostedNetworkState;

		private WlanInterfaceInfo m_currentInterface = null;
		/// <summary>
		/// SelectedWi-Fi module
		/// </summary>
		public WlanInterfaceInfo CurrentInterface
		{
			get
			{
				return m_currentInterface;
			}
		}

		/// <summary>
		/// List avaliable Wi-Fi adapters
		/// </summary>
		public List<WlanInterfaceInfo> AvaliableWiFiList
		{
			get;
			private set;
		}

		public List<WlanAvaliableNetwork> AvailableNetworks
		{
			get;
			private set;
		}

		private Dictionary<string, WlanNetwork> m_Stations = new Dictionary<string, WlanNetwork>();

		private bool m_connected;
		public bool IsConnected
		{
			get { return m_connected; }
		}

		/// <summary>
		/// If Network started
		/// </summary>
		public bool IsHostedNetworkStarted
		{
			get
			{
				return (this.m_HostedNetworkState == WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_active);
			}
		}

		public WlanHelper()
		{
			WlanHandle = IntPtr.Zero;
			m_connected = false;
			WlanVersion = 0;
			AvaliableWiFiList = new List<WlanInterfaceInfo>();
			m_notifyCallback = new WLAN_NOTIFICATION_CALLBACK(OnNotify);

			OperatingSystem os = Environment.OSVersion;
			Version ver = os.Version;
			if (ver.Major == 6)
				this.OpenWlanHadle(WLAN_API_VERSION_2_0);
			if (ver.Major == 5)
				this.OpenWlanHadle(WLAN_API_VERSION_1_0);

			InitNotifycation();
		}

		public WlanHelper(uint WlanApiVersion)
		{
			WlanHandle = IntPtr.Zero;
			WlanVersion = 0;
			m_connected = false;
			AvaliableWiFiList = new List<WlanInterfaceInfo>();
			m_notifyCallback = new WLAN_NOTIFICATION_CALLBACK(OnNotify);
			OpenWlanHadle(WlanApiVersion);
			InitNotifycation();
		}

		~WlanHelper()
		{
			this.Dispose();
		}

		private void InitNotifycation()
		{
			WLAN_NOTIFICATION_SOURCE notifySource;
			uint error = WlanRegisterNotification(WlanHandle, WLAN_NOTIFICATION_SOURCE.All, true, this.m_notifyCallback,
														IntPtr.Zero, IntPtr.Zero, out notifySource);
			if (error != ERROR_SUCCESS)
				ThrowIfError((int)error);
		}

		private string getOSInfo()
		{
			OperatingSystem os = Environment.OSVersion;
			Version vs = os.Version;

			string operatingSystem = "";

			if (os.Platform == PlatformID.Win32Windows)
			{
				//This is a pre-NT version of Windows
				switch (vs.Minor)
				{
					case 0:
						operatingSystem = "95";
						break;
					case 10:
						if (vs.Revision.ToString() == "2222A")
							operatingSystem = "98SE";
						else
							operatingSystem = "98";
						break;
					case 90:
						operatingSystem = "Me";
						break;
					default:
						break;
				}
			}
			else if (os.Platform == PlatformID.Win32NT)
			{
				switch (vs.Major)
				{
					case 3:
						operatingSystem = "NT 3.51";
						break;
					case 4:
						operatingSystem = "NT 4.0";
						break;
					case 5:
						if (vs.Minor == 0)
							operatingSystem = "2000";
						else
							operatingSystem = "XP";
						break;
					case 6:
						if (vs.Minor == 0)
							operatingSystem = "Vista";
						else
							operatingSystem = "7";
						break;
					default:
						break;
				}
			}
			return operatingSystem;
		}

		private void onHostedNetworkStarted()
		{
			this.m_HostedNetworkState = WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_active;

			EventHandler handler = HostedNetworkStarted;
			if (handler != null)
			{
				this.HostedNetworkStarted(this, EventArgs.Empty);
			}
		}

		private void onHostedNetworkStopped()
		{
			this.m_HostedNetworkState = WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_idle;

			EventHandler handler = HostedNetworkStopped;
			if (handler != null)
			{
				this.HostedNetworkStopped(this, EventArgs.Empty);
			}
		}

		private void onHostedNetworkAvailable()
		{
			this.m_HostedNetworkState = WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_idle;

			EventHandler handler = HostedNetworkAvailable;
			if (handler != null)
			{
				this.HostedNetworkAvailable(this, EventArgs.Empty);
			}
		}

		private void onStationJoin(WLAN_HOSTED_NETWORK_PEER_STATE stationState)
		{
			WlanNetwork pStation = new WlanNetwork(stationState);
			this.m_Stations[pStation.MacAddress] = pStation;

			if (this.StationJoin != null)
			{
				this.StationJoin(this, EventArgs.Empty);
			}
		}

		private void onStationLeave(WLAN_HOSTED_NETWORK_PEER_STATE stationState)
		{
			this.m_Stations.Remove(ConvertToString(stationState.PeerMacAddress));

			if (this.StationLeave != null)
			{
				this.StationLeave(this, EventArgs.Empty);
			}
		}

		private void onStationStateChange(WLAN_HOSTED_NETWORK_PEER_STATE stationState)
		{
			if (this.StationStateChange != null)
			{
				this.StationStateChange(this, EventArgs.Empty);
			}
		}


		/// <summary>
		/// Information about hardware Wi-Fi
		/// </summary>
		public class WlanInterfaceInfo
		{
			public Guid InterfaceGuid
			{
				get;
				set;
			}

			public string InterfaceDescription
			{
				get;
				set;
			}

			public string InterfaceState
			{
				get;
				set;
			}
		}

		/// <summary>
		/// Information about available network
		/// </summary>
		public class WlanAvaliableNetwork
		{
			public string ProfileName
			{
				get;
				set;
			}

			public uint NumberOfBssids
			{
				get;
				set;
			}

			public bool IsConnectable
			{
				get;
				set;
			}

			public uint ConnectableReason
			{
				get;
				set;
			}

			public uint SignalQuality
			{
				get;
				set;
			}

			public bool SecurityEnable
			{
				get;
				set;
			}

			public string SSID
			{
				get;
				set;
			}
		}

		internal class WlanNetwork
		{
			public WlanNetwork(WLAN_HOSTED_NETWORK_PEER_STATE state)
			{
				this.State = state;
			}

			public WLAN_HOSTED_NETWORK_PEER_STATE State { get; set; }

			public string MacAddress
			{
				get
				{
					return ConvertToString(this.State.PeerMacAddress);
				}
			}

			internal string ConvertToString(DOT11_MAC_ADDRESS mac)
			{
				var sb = new StringBuilder();

				sb.Append(ConvertToHexString(mac.one));
				sb.Append(":");
				sb.Append(ConvertToHexString(mac.two));
				sb.Append(":");
				sb.Append(ConvertToHexString(mac.three));
				sb.Append(":");
				sb.Append(ConvertToHexString(mac.four));
				sb.Append(":");
				sb.Append(ConvertToHexString(mac.five));
				sb.Append(":");
				sb.Append(ConvertToHexString(mac.six));

				return sb.ToString();
			}

			internal string ConvertToHexString(byte value)
			{
				return Convert.ToString(value, 0x10).PadLeft(2, '0');
			}
		}

		/// <summary>
		/// Defines flags passed to <see cref="WlanGetAvailableNetworkList"/>.
		/// </summary>
		[Flags()]
		internal enum WlanGetAvailableNetworkFlags
		{
			/// <summary>
			/// Include all ad-hoc network profiles in the available network list, including profiles that are not visible.
			/// </summary>
			IncludeAllAdhocProfiles = 0x00000001,
			/// <summary>
			/// Include all hidden network profiles in the available network list, including profiles that are not visible.
			/// </summary>
			IncludeAllManualHiddenProfiles = 0x00000002
		}

		/// <summary >
		/// Interface state enums
		/// </summary >
		internal enum WLAN_INTERFACE_STATE : int
		{
			wlan_interface_state_not_ready = 0,
			wlan_interface_state_connected,
			wlan_interface_state_ad_hoc_network_formed,
			wlan_interface_state_disconnecting,
			wlan_interface_state_disconnected,
			wlan_interface_state_associating,
			wlan_interface_state_discovering,
			wlan_interface_state_authenticating
		};

		/// <summary >
		/// Stores interface info
		/// </summary >
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct WLAN_INTERFACE_INFO
		{
			/// GUID->_GUID
			public Guid InterfaceGuid;
			/// WCHAR[256]
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
			public string strInterfaceDescription;
			/// WLAN_INTERFACE_STATE->_WLAN_INTERFACE_STATE
			public WLAN_INTERFACE_STATE isState;
		}

		/// <summary >
		/// This structure contains an array of NIC information
		/// </summary >
		[StructLayout(LayoutKind.Sequential)]
		internal struct WLAN_INTERFACE_INFO_LIST
		{
			public WLAN_INTERFACE_INFO_LIST(IntPtr pList)
			{
				// The first 4 bytes are the number of WLAN_INTERFACE_INFO structures.
				dwNumberofItems = Marshal.ReadInt32(pList, 0);
				// The next 4 bytes are the index of the current item in the unmanaged API.
				dwIndex = Marshal.ReadInt32(pList, 4);
				// Construct the array of WLAN_INTERFACE_INFO structures.
				InterfaceInfo = new WLAN_INTERFACE_INFO[dwNumberofItems];
				for (int i = 0; i < dwNumberofItems; i++)
				{
					// The offset of the array of structures is 8 bytes past the beginning.
					// Then, take the index and multiply it by the number of bytes in the
					// structure.The length of the WLAN_INTERFACE_INFO structure is 532 bytes - this
					// was determined by doing a sizeof(WLAN_INTERFACE_INFO) in an unmanaged C++ app.
					IntPtr pItemList = new IntPtr(pList.ToInt32() + (i * 532) + 8);

					// Construct the WLAN_INTERFACE_INFO structure, marshal the unmanaged structure into it,
					// then copy it to the array of structures.
					WLAN_INTERFACE_INFO wii = new WLAN_INTERFACE_INFO();
					wii = (WLAN_INTERFACE_INFO)Marshal.PtrToStructure(pItemList, typeof(WLAN_INTERFACE_INFO));
					InterfaceInfo[i] = wii;
				}
			}

			public Int32 dwNumberofItems;
			public Int32 dwIndex;
			public WLAN_INTERFACE_INFO[] InterfaceInfo;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct WLAN_AVAILABLE_NETWORK
		{
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
			public string strProfileName;
			public DOT11_SSID dot11Ssid;
			public DOT11_BSS_TYPE dot11BssType;
			public uint uNumberOfBssids;
			public bool bNetworkConnectable;
			public uint wlanNotConnectableReason;
			public uint uNumberOfPhyTypes;
			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
			public DOT11_PHY_TYPE[] dot11PhyTypes;
			public bool bMorePhyTypes;
			public uint wlanSignalQuality;
			public bool bSecurityEnabled;
			public DOT11_AUTH_ALGORITHM dot11DefaultAuthAlgorithm;
			public DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm;
			public uint dwFlags;
			public uint dwReserved;
		}

		internal enum DOT11_CIPHER_ALGORITHM : uint
		{
			DOT11_CIPHER_ALGO_NONE = 0x00,
			DOT11_CIPHER_ALGO_WEP40 = 0x01,
			DOT11_CIPHER_ALGO_TKIP = 0x02,
			DOT11_CIPHER_ALGO_CCMP = 0x04,
			DOT11_CIPHER_ALGO_WEP104 = 0x05,
			DOT11_CIPHER_ALGO_WPA_USE_GROUP = 0x100,
			DOT11_CIPHER_ALGO_RSN_USE_GROUP = 0x100,
			DOT11_CIPHER_ALGO_WEP = 0x101,
			DOT11_CIPHER_ALGO_IHV_START = 0x80000000,
			DOT11_CIPHER_ALGO_IHV_END = 0xffffffff
		};

		internal enum DOT11_AUTH_ALGORITHM : uint
		{
			DOT11_AUTH_ALGO_80211_OPEN = 1,
			DOT11_AUTH_ALGO_80211_SHARED_KEY = 2,
			DOT11_AUTH_ALGO_WPA = 3,
			DOT11_AUTH_ALGO_WPA_PSK = 4,
			DOT11_AUTH_ALGO_WPA_NONE = 5,
			DOT11_AUTH_ALGO_RSNA = 6,
			DOT11_AUTH_ALGO_RSNA_PSK = 7,
			DOT11_AUTH_ALGO_IHV_START = 0x80000000,
			DOT11_AUTH_ALGO_IHV_END = 0xffffffff
		};

		internal enum DOT11_BSS_TYPE
		{
			dot11_BSS_type_infrastructure = 1,
			dot11_BSS_type_independent = 2,
			dot11_BSS_type_any = 3
		};

		internal enum DOT11_PHY_TYPE : uint
		{
			dot11_phy_type_unknown = 0,
			dot11_phy_type_any = 0,
			dot11_phy_type_fhss = 1,
			dot11_phy_type_dsss = 2,
			dot11_phy_type_irbaseband = 3,
			dot11_phy_type_ofdm = 4,
			dot11_phy_type_hrdsss = 5,
			dot11_phy_type_erp = 6,
			dot11_phy_type_ht = 7,
			dot11_phy_type_IHV_start = 0x80000000,
			dot11_phy_type_IHV_end = 0xffffffff
		};

		internal enum WLAN_FILTER_LIST_TYPE
		{
			wlan_filter_list_type_gp_permit,
			wlan_filter_list_type_gp_deny,
			wlan_filter_list_type_user_permit,
			wlan_filter_list_type_user_deny
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		internal struct DOT11_MAC_ADDRESS
		{
			public byte one;
			public byte two;
			public byte three;
			public byte four;
			public byte five;
			public byte six;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
		internal struct DOT11_SSID
		{
			/// ULONG->unsigned int
			public uint uSSIDLength;
			/// UCHAR[]
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
			public string ucSSID;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct WLAN_AVAILABLE_NETWORK_LIST
		{
			internal uint dwNumberOfItems;
			internal uint dwIndex;
			internal WLAN_AVAILABLE_NETWORK[] wlanAvailableNetwork;

			internal WLAN_AVAILABLE_NETWORK_LIST(IntPtr ppAvailableNetworkList)
			{
				dwNumberOfItems = (uint)Marshal.ReadInt32(ppAvailableNetworkList);
				dwIndex = (uint)Marshal.ReadInt32(ppAvailableNetworkList, 4);
				wlanAvailableNetwork = new WLAN_AVAILABLE_NETWORK[dwNumberOfItems];

				for (int i = 0; i < dwNumberOfItems; i++)
				{
					IntPtr pWlanAvailableNetwork = new IntPtr(ppAvailableNetworkList.ToInt32() + i * Marshal.SizeOf(typeof(WLAN_AVAILABLE_NETWORK)) + 8);
					wlanAvailableNetwork[i] = (WLAN_AVAILABLE_NETWORK)Marshal.PtrToStructure(pWlanAvailableNetwork, typeof(WLAN_AVAILABLE_NETWORK));
				}
			}
		}

		[Flags()]
		internal enum WlanProfileFlags
		{
			/// <remarks>
			/// The only option available on Windows XP SP2.
			/// </remarks>
			AllUser = 0,
			GroupPolicy = 1,
			User = 2
		}

		/// <summary>
		/// Defines the access mask of an all-user profile.
		/// </summary>
		[Flags()]
		internal enum WlanAccessFlag : uint
		{
			/// <summary>
			/// The user can view profile permissions.
			/// </summary>
			ReadAccess = 0x00020000 | 0x0001,
			/// <summary>
			/// The user has read access, and the user can also connect to and disconnect from a network using the profile.
			/// </summary>
			ExecuteAccess = ReadAccess | 0x0020,
			/// <summary>
			/// The user has execute access and the user can also modify and delete permissions associated with a profile.
			/// </summary>
			WriteAccess = ReadAccess | ExecuteAccess | 0x0002 | 0x00010000 | 0x00040000
		}

		internal enum WLAN_INTF_OPCODE
		{
			wlan_intf_opcode_autoconf_start = 0x000000000,
			wlan_intf_opcode_autoconf_enabled,
			wlan_intf_opcode_background_scan_enabled,
			wlan_intf_opcode_media_streaming_mode,
			wlan_intf_opcode_radio_state,
			wlan_intf_opcode_bss_type,
			wlan_intf_opcode_interface_state,
			wlan_intf_opcode_current_connection,
			wlan_intf_opcode_channel_number,
			wlan_intf_opcode_supported_infrastructure_auth_cipher_pairs,
			wlan_intf_opcode_supported_adhoc_auth_cipher_pairs,
			wlan_intf_opcode_supported_country_or_region_string_list,
			wlan_intf_opcode_current_operation_mode,
			wlan_intf_opcode_supported_safe_mode,
			wlan_intf_opcode_certified_safe_mode,
			wlan_intf_opcode_hosted_network_capable,
			wlan_intf_opcode_autoconf_end = 0x0fffffff,
			wlan_intf_opcode_msm_start = 0x10000100,
			wlan_intf_opcode_statistics,
			wlan_intf_opcode_rssi,
			wlan_intf_opcode_msm_end = 0x1fffffff,
			wlan_intf_opcode_security_start = 0x20010000,
			wlan_intf_opcode_security_end = 0x2fffffff,
			wlan_intf_opcode_ihv_start = 0x30000000,
			wlan_intf_opcode_ihv_end = 0x3fffffff
		} ;

		internal enum WLAN_CONNECTION_MODE
		{
			wlan_connection_mode_profile,
			wlan_connection_mode_temporary_profile,
			wlan_connection_mode_discovery_secure,
			wlan_connection_mode_discovery_unsecure,
			wlan_connection_mode_auto,
			wlan_connection_mode_invalid
		} ;

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct WLAN_CONNECTION_ATTRIBUTES
		{
			/// WLAN_INTERFACE_STATE->_WLAN_INTERFACE_STATE
			public WLAN_INTERFACE_STATE isState;
			/// WLAN_CONNECTION_MODE->_WLAN_CONNECTION_MODE
			public WLAN_CONNECTION_MODE wlanConnectionMode;
			/// WCHAR[256]
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
			public string strProfileName;
			/// WLAN_ASSOCIATION_ATTRIBUTES->_WLAN_ASSOCIATION_ATTRIBUTES
			public WLAN_ASSOCIATION_ATTRIBUTES wlanAssociationAttributes;
			/// WLAN_SECURITY_ATTRIBUTES->_WLAN_SECURITY_ATTRIBUTES
			public WLAN_SECURITY_ATTRIBUTES wlanSecurityAttributes;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
		internal struct WLAN_ASSOCIATION_ATTRIBUTES
		{
			/// DOT11_SSID->_DOT11_SSID
			public DOT11_SSID dot11Ssid;
			/// DOT11_BSS_TYPE->_DOT11_BSS_TYPE
			public DOT11_BSS_TYPE dot11BssType;
			/// DOT11_MAC_ADDRESS->UCHAR[6]
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
			public string dot11Bssid;
			/// DOT11_PHY_TYPE->_DOT11_PHY_TYPE
			public DOT11_PHY_TYPE dot11PhyType;
			/// ULONG->unsigned int
			public uint uDot11PhyIndex;
			/// WLAN_SIGNAL_QUALITY->ULONG->unsigned int
			public uint wlanSignalQuality;
			/// ULONG->unsigned int
			public uint ulRxRate;
			/// ULONG->unsigned int
			public uint ulTxRate;
		}

		[StructLayout(LayoutKind.Sequential)]
		internal struct WLAN_SECURITY_ATTRIBUTES
		{
			/// <summary>
			/// BOOL->int
			/// </summary>
			[MarshalAs(UnmanagedType.Bool)]
			public bool bSecurityEnabled;
			/// <summary>
			/// BOOL->int
			/// </summary>
			[MarshalAs(UnmanagedType.Bool)]
			public bool bOneXEnabled;
			/// <summary>
			/// DOT11_AUTH_ALGORITHM->_DOT11_AUTH_ALGORITHM
			/// </summary>
			public DOT11_AUTH_ALGORITHM dot11AuthAlgorithm;
			/// <summary>
			/// DOT11_CIPHER_ALGORITHM->_DOT11_CIPHER_ALGORITHM
			/// </summary>
			public DOT11_CIPHER_ALGORITHM dot11CipherAlgorithm;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct WLAN_CONNECTION_PARAMETERS
		{
			public WLAN_CONNECTION_MODE wlanConnectionMode;
			public string strProfile;
			public DOT11_SSID[] pDot11Ssid;
			public DOT11_BSSID_LIST[] pDesiredBssidList;
			public DOT11_BSS_TYPE dot11BssType;
			public uint dwFlags;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct DOT11_BSSID_LIST
		{
			NDIS_OBJECT_HEADER Header;
			ulong uNumOfEntries;
			ulong uTotalNumOfEntries;
			IntPtr BSSIDs;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct NDIS_OBJECT_HEADER
		{
			byte Type;
			byte Revision;
			ushort Size;
		}

		/// <summary>
		/// Contains information provided when registering for notifications.
		/// </summary>
		[StructLayout(LayoutKind.Sequential)]
		internal struct WLAN_NOTIFICATION_DATA
		{
			/// <summary>
			/// Specifies where the notification comes from.
			/// </summary>
			/// <remarks>
			/// On Windows XP SP2, this field must be set to <see cref="WlanNotificationSource.None"/>, <see cref="WlanNotificationSource.All"/> or <see cref="WlanNotificationSource.ACM"/>.
			/// </remarks>
			public WLAN_NOTIFICATION_SOURCE notificationSource;
			/// <summary>
			/// Indicates the type of notification. The value of this field indicates what type of associated data will be present in <see cref="dataPtr"/>.
			/// </summary>
			public int notificationCode;
			/// <summary>
			/// Indicates which interface the notification is for.
			/// </summary>
			public Guid interfaceGuid;
			/// <summary>
			/// Specifies the size of <see cref="dataPtr"/>, in bytes.
			/// </summary>
			public int dataSize;
			/// <summary>
			/// Pointer to additional data needed for the notification, as indicated by <see cref="notificationCode"/>.
			/// </summary>
			public IntPtr dataPtr;
			/// <summary>
			/// Gets the notification code (in the correct enumeration type) according to the notification source.
			/// </summary>
			public object NotificationCode
			{
				get
				{
					if (notificationSource == WLAN_NOTIFICATION_SOURCE.MSM)
						return (WLAN_NOTIFICATION_CODE_MSM)notificationCode;
					else if (notificationSource == WLAN_NOTIFICATION_SOURCE.ACM)
						return (WLAN_NOTIFICATION_CODE_ACM)notificationCode;
					else
						return notificationCode;
				}

			}
		}

		internal enum WLAN_NOTIFICATION_CODE_ACM
		{
			AutoconfEnabled = 1,
			AutoconfDisabled,
			BackgroundScanEnabled,
			BackgroundScanDisabled,
			BssTypeChange,
			PowerSettingChange,
			ScanComplete,
			ScanFail,
			ConnectionStart,
			ConnectionComplete,
			ConnectionAttemptFail,
			FilterListChange,
			InterfaceArrival,
			InterfaceRemoval,
			ProfileChange,
			ProfileNameChange,
			ProfilesExhausted,
			NetworkNotAvailable,
			NetworkAvailable,
			Disconnecting,
			Disconnected,
			AdhocNetworkStateChange
		}

		internal enum WLAN_NOTIFICATION_CODE_MSM
		{
			wlan_notification_msm_start = 0,
			wlan_notification_msm_associating,
			wlan_notification_msm_associated,
			wlan_notification_msm_authenticating,
			wlan_notification_msm_connected,
			wlan_notification_msm_roaming_start,
			wlan_notification_msm_roaming_end,
			wlan_notification_msm_radio_state_change,
			wlan_notification_msm_signal_quality_change,
			wlan_notification_msm_disassociating,
			wlan_notification_msm_disconnected,
			wlan_notification_msm_peer_join,
			wlan_notification_msm_peer_leave,
			wlan_notification_msm_adapter_removal,
			wlan_notification_msm_adapter_operation_mode_change,
			wlan_notification_msm_end
		};

		[Flags]
		internal enum WLAN_NOTIFICATION_SOURCE : uint
		{
			None = 0,
			/// <summary>
			/// All notifications, including those generated by the 802.1X module.
			/// </summary>
			All = 0X0000FFFF,
			/// <summary>
			/// Notifications generated by the auto configuration module.
			/// </summary>
			ACM = 0X00000008,
			/// <summary>
			/// Notifications generated by MSM.
			/// </summary>
			MSM = 0X00000010,
			/// <summary>
			/// Notifications generated by the security module.
			/// </summary>
			Security = 0X00000020,
			/// <summary>
			/// Notifications generated by independent hardware vendors (IHV).
			/// </summary>
			IHV = 0X00000040
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		public struct WLAN_PROFILE_INFO_LIST
		{
			public uint dwNumberOfItems;
			public uint dwIndex;
			public WLAN_PROFILE_INFO[] ProfileInfo;

			public WLAN_PROFILE_INFO_LIST(IntPtr ppProfileList)
			{
				dwNumberOfItems = (uint)Marshal.ReadInt32(ppProfileList);
				dwIndex = (uint)Marshal.ReadInt32(ppProfileList, 4);
				ProfileInfo = new WLAN_PROFILE_INFO[dwNumberOfItems];
				IntPtr ppProfileListTemp = new IntPtr(ppProfileList.ToInt32() + 8);

				for (int i = 0; i < dwNumberOfItems; i++)
				{
					ppProfileList = new IntPtr(ppProfileListTemp.ToInt32() + i * Marshal.SizeOf(typeof(WLAN_PROFILE_INFO)));
					ProfileInfo[i] = (WLAN_PROFILE_INFO)Marshal.PtrToStructure(ppProfileList, typeof(WLAN_PROFILE_INFO));
				}
			}
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		public struct WLAN_PROFILE_INFO
		{
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
			public string strProfileName;
			public uint dwFlags;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct WLAN_HOSTED_NETWORK_STATUS
		{
			public WLAN_HOSTED_NETWORK_STATE_CHANGE HostedNetworkState;
			public Guid IPDeviceID;
			public DOT11_MAC_ADDRESS wlanHostedNetworkBSSID;
			public DOT11_PHY_TYPE dot11PhyType;
			public uint ulChannelFrequency; // ULONG
			public uint dwNumberOfPeers; // DWORD
			public WLAN_HOSTED_NETWORK_PEER_STATE[] PeerList;
		}

		[StructLayout(LayoutKind.Sequential)]
		internal struct WLAN_HOSTED_NETWORK_PEER_STATE
		{
			public DOT11_MAC_ADDRESS PeerMacAddress;
			public WLAN_HOSTED_NETWORK_PEER_AUTH_STATE PeerAuthState;
		}

		public enum WLAN_HOSTED_NETWORK_PEER_AUTH_STATE
		{
			wlan_hosted_network_peer_state_invalid,
			wlan_hosted_network_peer_state_authenticated
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct WLAN_HOSTED_NETWORK_STATE_CHANGE
		{
			public WLAN_HOSTED_NETWORK_STATE OldState;
			public WLAN_HOSTED_NETWORK_STATE NewState;
			public WLAN_HOSTED_NETWORK_REASON Reason; // NewState;
		}

		public enum WLAN_HOSTED_NETWORK_REASON
		{
			wlan_hosted_network_reason_success = 0,
			wlan_hosted_network_reason_unspecified,
			wlan_hosted_network_reason_bad_parameters,
			wlan_hosted_network_reason_service_shutting_down,
			wlan_hosted_network_reason_insufficient_resources,
			wlan_hosted_network_reason_elevation_required,
			wlan_hosted_network_reason_read_only,
			wlan_hosted_network_reason_persistence_failed,
			wlan_hosted_network_reason_crypt_error,
			wlan_hosted_network_reason_impersonation,
			wlan_hosted_network_reason_stop_before_start,
			wlan_hosted_network_reason_interface_available,
			wlan_hosted_network_reason_interface_unavailable,
			wlan_hosted_network_reason_miniport_stopped,
			wlan_hosted_network_reason_miniport_started,
			wlan_hosted_network_reason_incompatible_connection_started,
			wlan_hosted_network_reason_incompatible_connection_stopped,
			wlan_hosted_network_reason_user_action,
			wlan_hosted_network_reason_client_abort,
			wlan_hosted_network_reason_ap_start_failed,
			wlan_hosted_network_reason_peer_arrived,
			wlan_hosted_network_reason_peer_departed,
			wlan_hosted_network_reason_peer_timeout,
			wlan_hosted_network_reason_gp_denied,
			wlan_hosted_network_reason_service_unavailable,
			wlan_hosted_network_reason_device_change,
			wlan_hosted_network_reason_properties_change,
			wlan_hosted_network_reason_virtual_station_blocking_use,
			wlan_hosted_network_reason_service_available_on_virtual_station
		}

		public enum WLAN_HOSTED_NETWORK_STATE
		{
			wlan_hosted_network_unavailable,
			wlan_hosted_network_idle,
			wlan_hosted_network_active
		}

		public enum DOT11_RADIO_STATE
		{
			dot11_radio_state_unknown,
			dot11_radio_state_on,
			dot11_radio_state_off
		}

		internal enum WLAN_HOSTED_NETWORK_NOTIFICATION_CODE
		{
			/// <summary>
			/// The Hosted Network state has changed.
			/// </summary>
			wlan_hosted_network_state_change = 0x00001000,
			/// <summary>
			/// The Hosted Network peer state has changed.
			/// </summary>
			wlan_hosted_network_peer_state_change,
			/// <summary>
			/// The Hosted Network radio state has changed.
			/// </summary>
			wlan_hosted_network_radio_state_change
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct WLAN_HOSTED_NETWORK_DATA_PEER_STATE_CHANGE
		{
			public WLAN_HOSTED_NETWORK_PEER_STATE OldState;
			public WLAN_HOSTED_NETWORK_PEER_STATE NewState;
			/// <summary>
			/// //NewState;
			/// </summary>
			public WLAN_HOSTED_NETWORK_REASON Reason;
		}

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
		internal struct WLAN_HOSTED_NETWORK_RADIO_STATE
		{
			DOT11_RADIO_STATE dot11SoftwareRadioState;
			DOT11_RADIO_STATE dot11HardwareRadioState;
		}

		public enum WLAN_OPCODE_VALUE_TYPE
		{
			wlan_opcode_value_type_query_only = 0,
			wlan_opcode_value_type_set_by_group_policy,
			wlan_opcode_value_type_set_by_user,
			wlan_opcode_value_type_invalid
		}

		public enum WLAN_HOSTED_NETWORK_OPCODE
		{
			wlan_hosted_network_opcode_connection_settings,
			wlan_hosted_network_opcode_security_settings,
			wlan_hosted_network_opcode_station_profile,
			wlan_hosted_network_opcode_enable
		}

		[StructLayout(LayoutKind.Sequential)] //, CharSet =  CharSet.Unicode)]
		internal struct WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS
		{
			public DOT11_SSID hostedNetworkSSID;
			public UInt32 dwMaxNumberOfPeers; // DWORD
		}

		[StructLayout(LayoutKind.Sequential)]
		internal struct DOT11_NETWORK_LIST
		{
			uint dwNumberOfItems;
			uint dwIndex;
			DOT11_NETWORK Network;
		}

		[StructLayout(LayoutKind.Sequential)]
		internal struct DOT11_NETWORK
		{
			DOT11_SSID dot11Ssid;
			DOT11_BSS_TYPE dot11BssType;
		}

		internal enum WLAN_AUTOCONF_OPCODE
		{
			wlan_autoconf_opcode_start = 0,
			wlan_autoconf_opcode_show_denied_networks = 1,
			wlan_autoconf_opcode_power_setting = 2,
			wlan_autoconf_opcode_only_use_gp_profiles_for_allowed_networks = 3,
			wlan_autoconf_opcode_allow_explicit_creds = 4,
			wlan_autoconf_opcode_block_period = 5,
			wlan_autoconf_opcode_allow_virtual_station_extensibility = 6,
			wlan_autoconf_opcode_end = 7
		}

		internal enum WL_DISPLAY_PAGES
		{
			WLConnectionPage,
			WLSecurityPage
		}

		/// <summary >
		/// Opens a connection to the server
		/// </summary >
		[DllImport("wlanapi.dll", SetLastError = true)]
		internal static extern Int32 WlanOpenHandle(UInt32 dwClientVersion, IntPtr pReserved, out UInt32 pdwNegotiatedVersion,
														out IntPtr phClientHandle);
		/// <summary >
		/// Closes a connection to the server
		/// </summary >
		[DllImport("wlanapi.dll", SetLastError = true)]
		internal static extern UInt32 WlanCloseHandle(IntPtr hClientHandle, IntPtr pReserved);
		/// <summary >
		/// Enumerates all wireless interfaces in the laptop
		/// </summary >
		[DllImport("wlanapi.dll", SetLastError = true)]
		internal static extern UInt32 WlanEnumInterfaces(IntPtr hClientHandle, IntPtr pReserved, out IntPtr ppInterfaceList);
		/// <summary >
		/// Frees memory returned by native WiFi functions
		/// </summary >
		[DllImport("wlanapi.dll", SetLastError = true)]
		internal static extern void WlanFreeMemory(IntPtr pmemory);

		[DllImport("Wlanapi.dll", SetLastError = true)]
		internal static extern int WlanGetAvailableNetworkList(IntPtr hClientHandle, ref Guid pInterfaceGuid, uint dwFlags,
																IntPtr pReserved, ref IntPtr ppAvailableNetworkList);

		[DllImport("wlanapi.dll")]
		internal static extern int WlanSetProfile(IntPtr clientHandle, [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
			  [In] WlanProfileFlags flags, [In, MarshalAs(UnmanagedType.LPWStr)] string profileXml,
			  [In, Optional, MarshalAs(UnmanagedType.LPWStr)] string allUserProfileSecurity,
			  bool overwrite, IntPtr pReserved, [Out] out WlanReasonCode reasonCode);

		[DllImport("Wlanapi", EntryPoint = "WlanQueryInterface")]
		internal static extern uint WlanQueryInterface(IntPtr hClientHandle, ref Guid pInterfaceGuid, WLAN_INTF_OPCODE OpCode,
							IntPtr pReserved, [Out] out uint pdwDataSize, ref IntPtr ppData, IntPtr pWlanOpcodeValueType);

		[DllImport("Wlanapi.dll", SetLastError = true)]
		internal static extern uint WlanScan(IntPtr hClientHandle, ref Guid pInterfaceGuid, IntPtr pDot11Ssid,
											IntPtr pIeData, IntPtr pReserved);

		[DllImport("Wlanapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
		public static extern uint WlanReasonCodeToString(uint dwReasonCode, uint dwBufferSize, string pStringBuffer, IntPtr pReserved);

		internal delegate void WLAN_NOTIFICATION_CALLBACK(ref WLAN_NOTIFICATION_DATA notificationData, IntPtr context);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanRegisterNotification")]
		internal static extern uint WlanRegisterNotification(IntPtr hClientHandle, WLAN_NOTIFICATION_SOURCE dwNotifSource,
			 bool bIgnoreDuplicate, WLAN_NOTIFICATION_CALLBACK funcCallback,
			 IntPtr pCallbackContext, IntPtr pReserved, [Out] out WLAN_NOTIFICATION_SOURCE pdwPrevNotifSource);

		[DllImport("Wlanapi.dll", SetLastError = true)]
		internal static extern uint WlanDisconnect(IntPtr hClientHandle, ref Guid pInterfaceGuid, IntPtr pReserved);

		[DllImport("Wlanapi.dll", SetLastError = true)]
		internal static extern uint WlanConnect(IntPtr hClientHandle, ref Guid pInterfaceGuid,
												ref WLAN_CONNECTION_PARAMETERS pConnectionParameters, IntPtr pReserved);

		[DllImport("Wlanapi.dll", SetLastError = true)]
		internal static extern uint WlanGetProfileList(IntPtr hClientHandle, ref Guid pInterfaceGuid,
													IntPtr pReserved, ref IntPtr ppProfileList);

		[DllImport("Wlanapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
		public static extern uint WlanGetProfile(IntPtr hClientHandle, ref Guid pInterfaceGuid, string strProfileName, IntPtr pReserved,
												ref string pstrProfileXml, ref uint pdwFlags, ref uint pdwGrantedAccess);

		[DllImport("Wlanapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
		internal static extern uint WlanDeleteProfile(IntPtr hClientHandle, ref Guid pInterfaceGuid,
													string strProfileName, IntPtr pReserved);

		[DllImport("Wlanapi.dll")]
		internal static extern uint WlanSetInterface(IntPtr hHandle, ref Guid pInterfaceGuid, WLAN_INTF_OPCODE OpCode,
													uint dwDataSize, ref object obj, IntPtr pReserved);

		[DllImport("Wlanapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
		internal static extern uint WlanSetProfileList(IntPtr hClientHandle, ref Guid pInterfaceGuid, uint dwItems,
														string[] strProfileNames, IntPtr pReserved);

		[DllImport("Wlanapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
		internal static extern uint WlanRenameProfile(IntPtr hClientHandle, ref Guid pInterfaceGuid, string strOldProfileName,
														string strNewProfileName, IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkSetProperty")]
		internal static extern uint WlanHostedNetworkSetProperty(IntPtr hClientHandle, WLAN_HOSTED_NETWORK_OPCODE OpCode,
			uint dwDataSize, IntPtr pvData, [Out] out WLAN_HOSTED_NETWORK_REASON pFailReason, IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkQueryStatus")]
		internal static extern uint WlanHostedNetworkQueryStatus(IntPtr hClientHandle,
																[Out] out WLAN_HOSTED_NETWORK_STATUS pWlanHostedNetworkStatus, IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkQuerySecondaryKey")]
		internal static extern uint WlanHostedNetworkQuerySecondaryKey(IntPtr hClientHandle, [Out] out uint pKeyLength,
					 [Out, MarshalAs(UnmanagedType.LPStr)] out string ppucKeyData, [Out] out bool pbIsPassPhrase,
					 [Out] out bool pbPersistent, [Out] out WLAN_HOSTED_NETWORK_REASON pFailReason, IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkSetSecondaryKey")]
		internal static extern uint WlanHostedNetworkSetSecondaryKey(IntPtr hClientHandle, uint dwKeyLength,
					[In, MarshalAs(UnmanagedType.LPStr)] string pucKeyData, bool bIsPassPhrase, bool bPersistent,
					[Out] out WLAN_HOSTED_NETWORK_REASON pFailReason, IntPtr pReserved);


		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkForceStart")]
		internal static extern uint WlanHostedNetworkForceStart(IntPtr hClientHandle, [Out] out WLAN_HOSTED_NETWORK_REASON pFailReason, IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkForceStop")]
		internal static extern uint WlanHostedNetworkForceStop(IntPtr hClientHandle, [Out] out WLAN_HOSTED_NETWORK_REASON pFailReason, IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkInitSettings")]
		internal static extern uint WlanHostedNetworkInitSettings(IntPtr hClientHandle, [Out] out WLAN_HOSTED_NETWORK_REASON pFailReason, IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkRefreshSecuritySettings")]
		internal static extern uint WlanHostedNetworkRefreshSecuritySettings(IntPtr hClientHandle, [Out] out WLAN_HOSTED_NETWORK_REASON pFailReason,
																			IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkStartUsing")]
		internal static extern uint WlanHostedNetworkStartUsing(IntPtr hClientHandle, [Out] out WLAN_HOSTED_NETWORK_REASON pFailReason, IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkStopUsing")]
		internal static extern uint WlanHostedNetworkStopUsing(IntPtr hClientHandle, [Out] out WLAN_HOSTED_NETWORK_REASON pFailReason, IntPtr pReserved);

		[DllImport("Wlanapi.dll", EntryPoint = "WlanHostedNetworkQueryProperty")]
		internal static extern uint WlanHostedNetworkQueryProperty(IntPtr hClientHandle, WLAN_HOSTED_NETWORK_OPCODE OpCode, [Out] out uint pDataSize,
			[Out] out IntPtr ppvData, [Out] out WLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType, IntPtr pReserved);

		[DllImport("Wlanapi.dll")]
		internal static extern uint WlanGetFilterList(IntPtr handle, [In] WLAN_FILTER_LIST_TYPE filterList, IntPtr reserved,
														 [Out] out DOT11_NETWORK_LIST ppNetworkList);
		[DllImport("Wlanapi.dll")]
		internal extern static uint WlanQueryAutoConfigParameter(IntPtr hClientHandle, WLAN_AUTOCONF_OPCODE OpCode,
														IntPtr pReserved, out uint pdwDataSize, out IntPtr ppData,
														out WLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType);

		[DllImport("Wlanapi.dll")]
		internal static extern uint WlanRegisterVirtualStationNotification(IntPtr hClientHandle, bool bRegister, IntPtr pvReserved);

		[DllImport("Wlanapi.dll")]
		internal static extern uint WlanGetProfileCustomUserData(IntPtr hClientHandle, ref Guid pInterfaceGuid, string strProfileName,
																IntPtr pReserved, out uint pdwDataSize, out byte ppData);

		[DllImport("Wlanui.dll")]
		internal static extern uint WlanUIEditProfile(uint dwClientVersion, string wstrProfileName, ref Guid pInterfaceGuid,
									IntPtr hWnd, WL_DISPLAY_PAGES wlStartPage, IntPtr pReserved, out  WlanReasonCode pWlanReasonCode);


		#region Private Functions
		/// <summary >
		///get NIC state
		/// </summary >
		private string getStateDescription(WLAN_INTERFACE_STATE state)
		{
			string stateDescription = string.Empty;
			switch (state)
			{
				case WLAN_INTERFACE_STATE.wlan_interface_state_not_ready:
					stateDescription = "not ready to operate";
					break;
				case WLAN_INTERFACE_STATE.wlan_interface_state_connected:
					stateDescription = "connected";
					break;
				case WLAN_INTERFACE_STATE.wlan_interface_state_ad_hoc_network_formed:
					stateDescription = "first node in an adhoc network";
					break;
				case WLAN_INTERFACE_STATE.wlan_interface_state_disconnecting:
					stateDescription = "disconnecting";
					break;
				case WLAN_INTERFACE_STATE.wlan_interface_state_disconnected:
					stateDescription = "disconnected";
					break;
				case WLAN_INTERFACE_STATE.wlan_interface_state_associating:
					stateDescription = "associating";
					break;
				case WLAN_INTERFACE_STATE.wlan_interface_state_discovering:
					stateDescription = "discovering";
					break;
				case WLAN_INTERFACE_STATE.wlan_interface_state_authenticating:
					stateDescription = "authenticating";
					break;

				default:
					break;
			}

			return stateDescription;
		}
		#endregion

		private void OnNotify(ref WLAN_NOTIFICATION_DATA data, IntPtr context)
		{
			switch (data.notificationCode)
			{
				case (int)WLAN_HOSTED_NETWORK_NOTIFICATION_CODE.wlan_hosted_network_state_change:
					if (data.dataSize > 0 && data.dataPtr != IntPtr.Zero)
					{
						WLAN_HOSTED_NETWORK_STATE_CHANGE pStateChange = (WLAN_HOSTED_NETWORK_STATE_CHANGE)Marshal.PtrToStructure(data.dataPtr,
																									typeof(WLAN_HOSTED_NETWORK_STATE_CHANGE));
						switch (pStateChange.NewState)
						{
							case WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_active:
								this.onHostedNetworkStarted();
								break;

							case WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_idle:
								if (pStateChange.OldState == WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_active)
								{
									this.onHostedNetworkStopped();
								}
								else
								{
									this.onHostedNetworkAvailable();
								}
								break;

							case WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_unavailable:
								if (pStateChange.OldState == WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_active)
								{
									this.onHostedNetworkStopped();
								}
								this.onHostedNetworkAvailable();
								break;
						}
					}
					break;

				case (int)WLAN_HOSTED_NETWORK_NOTIFICATION_CODE.wlan_hosted_network_peer_state_change:

					if (data.dataSize > 0 && data.dataPtr != IntPtr.Zero)
					{
						WLAN_HOSTED_NETWORK_DATA_PEER_STATE_CHANGE pPeerStateChange = (WLAN_HOSTED_NETWORK_DATA_PEER_STATE_CHANGE)Marshal.PtrToStructure(data.dataPtr,
																						typeof(WLAN_HOSTED_NETWORK_DATA_PEER_STATE_CHANGE));

						if (pPeerStateChange.NewState.PeerAuthState == WLAN_HOSTED_NETWORK_PEER_AUTH_STATE.wlan_hosted_network_peer_state_authenticated)
						{
							// Station joined the hosted network
							this.onStationJoin(pPeerStateChange.NewState);
						}
						else if (pPeerStateChange.NewState.PeerAuthState == WLAN_HOSTED_NETWORK_PEER_AUTH_STATE.wlan_hosted_network_peer_state_invalid)
						{
							// Station left the hosted network
							this.onStationLeave(pPeerStateChange.NewState);
						}
						else
						{
							// Authentication state changed
							this.onStationStateChange(pPeerStateChange.NewState);
						}
					}
					break;

				case (int)WLAN_HOSTED_NETWORK_NOTIFICATION_CODE.wlan_hosted_network_radio_state_change:
					if (data.dataSize > 0 && data.dataPtr != IntPtr.Zero)
					{
						WLAN_HOSTED_NETWORK_RADIO_STATE pRadioState = (WLAN_HOSTED_NETWORK_RADIO_STATE)Marshal.PtrToStructure(data.dataPtr,
																								typeof(WLAN_HOSTED_NETWORK_RADIO_STATE));
						// Do nothing for now
					}
					//else
					//{
					//    // // Shall NOT happen
					//    // _ASSERT(FAILSE);
					//}
					break;


				default:
					break;
			}
		}

		public void OpenWlanHadle()
		{
			CatchException((m_ErrorCode = WlanOpenHandle(WLAN_API_VERSION_2_0, IntPtr.Zero, out WlanVersion, out WlanHandle)));
			if (m_Win32Exc == null)
			{
				ThrowIfError(m_ErrorCode);
			}
		}

		public void OpenWlanHadle(uint WlanApiVersion)
		{
			CatchException((m_ErrorCode = WlanOpenHandle(WlanApiVersion, IntPtr.Zero, out WlanVersion, out WlanHandle)));
			if (m_Win32Exc != null)
			{
				ThrowIfError(m_ErrorCode);
			}
		}

		public void CloseWlanHandle()
		{
			if (WlanHandle != IntPtr.Zero)
				WlanCloseHandle(WlanHandle, IntPtr.Zero);
		}

		/// <summary >
		/// Enumerate wireless network adapters using wifi api
		/// </summary >
		public List<WlanInterfaceInfo> EnumerateNICs()
		{
			dynamic dict = new List<WlanInterfaceInfo>();

			if (WlanEnumInterfaces(WlanHandle, IntPtr.Zero, out ppInterfaceList) == ERROR_SUCCESS)
			{
				//Tranfer all values from IntPtr to WLAN_INTERFACE_INFO_LIST structure 
				interfaceList = new WLAN_INTERFACE_INFO_LIST(ppInterfaceList);

				for (int i = 0; i < interfaceList.dwNumberofItems; i++)
				{
					dict.Add(new WlanInterfaceInfo()
					{
						InterfaceGuid = interfaceList.InterfaceInfo[i].InterfaceGuid,
						InterfaceDescription = interfaceList.InterfaceInfo[i].strInterfaceDescription,
						InterfaceState = getStateDescription(interfaceList.InterfaceInfo[i].isState)
					});
				}

				if (ppInterfaceList != IntPtr.Zero)
					WlanFreeMemory(ppInterfaceList);
			}
			this.AvaliableWiFiList = dict;

			return dict;
		}

		public void RefreshNICs()
		{
			this.AvaliableWiFiList.Clear();
			this.AvaliableWiFiList = EnumerateNICs();
			if (AvaliableWiFiList.Count > 0)
				m_currentInterface = AvaliableWiFiList[0];
		}

		public List<WlanAvaliableNetwork> EnumearteNetworks(WlanInterfaceInfo iterface)
		{
			if (iterface == null)
				return null;

			List<WlanAvaliableNetwork> list = new List<WlanAvaliableNetwork>();
			IntPtr ppAvailableNetworkList = new IntPtr();
			Guid guid = iterface.InterfaceGuid;
			if (WlanGetAvailableNetworkList(WlanHandle, ref guid, (uint)WlanGetAvailableNetworkFlags.IncludeAllAdhocProfiles,
											new IntPtr(), ref  ppAvailableNetworkList) == ERROR_SUCCESS)
			{
				WLAN_AVAILABLE_NETWORK_LIST wlanAvailableNetworkList = new WLAN_AVAILABLE_NETWORK_LIST(ppAvailableNetworkList);
				WlanFreeMemory(ppAvailableNetworkList);

				for (int j = 0; j < wlanAvailableNetworkList.dwNumberOfItems; j++)
				{
					WLAN_AVAILABLE_NETWORK network = wlanAvailableNetworkList.wlanAvailableNetwork[j];
					list.Add(new WlanAvaliableNetwork()
					{
						SSID = network.dot11Ssid.ucSSID,
						SecurityEnable = network.bSecurityEnabled,
						SignalQuality = network.wlanSignalQuality,
						ProfileName = network.strProfileName,
						ConnectableReason = network.wlanNotConnectableReason,
						IsConnectable = network.bNetworkConnectable,
						NumberOfBssids = network.uNumberOfBssids
					});
					//  Console.WriteLine("Default Authentication: " + network.dot11DefaultAuthAlgorithm.ToString());
					//  Console.WriteLine("Default Cipher: " + network.dot11DefaultCipherAlgorithm.ToString());
				}
			}
			AvailableNetworks = list;

			return list;
		}

		public void RefreshNetworks()
		{
			this.AvailableNetworks.Clear();
			if (m_currentInterface != null)
				this.AvailableNetworks = EnumearteNetworks(m_currentInterface);
		}

		public void SomeMethod()
		{
			IntPtr handle = IntPtr.Zero;
			uint negotiatedVersion;
			try
			{
				if (WlanOpenHandle(1, IntPtr.Zero, out negotiatedVersion, out handle) != 0)
					return;

				IntPtr ptr;
				if (WlanEnumInterfaces(handle, IntPtr.Zero, out ptr) != 0)
					return;

				WLAN_INTERFACE_INFO_LIST infoList = new WLAN_INTERFACE_INFO_LIST(ptr);
				WlanFreeMemory(ptr);

				Guid guid;
				uint dataSize;
				WLAN_CONNECTION_ATTRIBUTES connection;
				// Call wlanqueryinterface for all the interfaces in the list
				for (int i = 0; i < infoList.dwNumberofItems; i++)
				{
					guid = infoList.InterfaceInfo[i].InterfaceGuid;
					if (WlanQueryInterface(handle, ref guid, WLAN_INTF_OPCODE.wlan_intf_opcode_current_connection,
											IntPtr.Zero, out dataSize, ref ptr, IntPtr.Zero) != 0)
						return;

					uint resultCode = WlanScan(handle, ref guid, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
					if (resultCode != 0)
						return;

					connection = (WLAN_CONNECTION_ATTRIBUTES)Marshal.PtrToStructure(ptr, typeof(WLAN_CONNECTION_ATTRIBUTES));

					// Do something here with the connection info....    
					WlanFreeMemory(ptr);
				}
			}
			finally
			{
				if (handle != IntPtr.Zero)
					WlanCloseHandle(handle, IntPtr.Zero);
			}
		}

		public string WlanReasonCodeTostringApi(uint ReasonCode)
		{
			uint dwBufferSize = 128;
			string pStringBuffer = new string(' ', (int)dwBufferSize);
			uint result = WlanReasonCodeToString(ReasonCode, dwBufferSize, pStringBuffer, new IntPtr());
			return pStringBuffer;
		}

		public void Connect(string profileName)
		{
			if (AvaliableWiFiList.Count == 0)
				return;

			Guid pInterGuid = AvaliableWiFiList[0].InterfaceGuid;
			WLAN_CONNECTION_PARAMETERS wlanConnectionParameters = new WLAN_CONNECTION_PARAMETERS();

			DOT11_SSID dotSsid = new DOT11_SSID();
			dotSsid.ucSSID = profileName;
			dotSsid.uSSIDLength = (uint)profileName.Length;

			wlanConnectionParameters.dot11BssType = DOT11_BSS_TYPE.dot11_BSS_type_any;
			wlanConnectionParameters.dwFlags = (uint)WlanGetAvailableNetworkFlags.IncludeAllManualHiddenProfiles;
			wlanConnectionParameters.strProfile = profileName;
			wlanConnectionParameters.pDesiredBssidList = null;
			wlanConnectionParameters.pDot11Ssid = new DOT11_SSID[] { dotSsid };
			wlanConnectionParameters.wlanConnectionMode = WLAN_CONNECTION_MODE.wlan_connection_mode_auto;

			int errorCode = (int)WlanConnect(WlanHandle, ref pInterGuid, ref wlanConnectionParameters, IntPtr.Zero);
			m_connected = (errorCode == 0 ? true : false);
			string errorMsg = WlanReasonCodeTostringApi((uint)errorCode);

			//WLAN_CONNECTION_PARAMETERS wlanConnectionParameters = new WLAN_CONNECTION_PARAMETERS();
			//wlanConnectionParameters.dot11BssType = DOT11_BSS_TYPE.dot11_BSS_type_any;
			//wlanConnectionParameters.dwFlags = 0;
			//wlanConnectionParameters.strProfile = "dlink";
			//wlanConnectionParameters.wlanConnectionMode = WLAN_CONNECTION_MODE.wlan_connection_mode_profile;
			//WlanConnect(WlanHandle, ref pInterGuid, ref wlanConnectionParameters, new IntPtr());
		}

		public void Disconnect()
		{
			if (AvaliableWiFiList.Count == 0)
				return;

			Guid pInterGuid = AvaliableWiFiList[0].InterfaceGuid;
			int errorCode = (int)WlanDisconnect(WlanHandle, ref pInterGuid, new IntPtr());
			string errorMsg = WlanReasonCodeTostringApi((uint)errorCode);
		}

		public string BuildProfileXml(string profileName, string key)
		{
			StringBuilder sb = new StringBuilder();
			sb.AppendLine("<?xml version=\"1.0\"?><WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\"><name></name><SSIDConfig><SSID><name></name></SSID></SSIDConfig><connectionType>ESS</connectionType><MSM><security><authEncryption><authentication>open</authentication><encryption>WEP</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>networkKey</keyType><protected>false</protected><keyMaterial></keyMaterial></sharedKey><keyIndex>0</keyIndex></security></MSM></WLANProfile>");
			sb.Insert(sb.ToString().IndexOf("</name>"), profileName);
			sb.Insert(sb.ToString().IndexOf("</name></SSID>"), profileName);
			sb.Insert(sb.ToString().IndexOf("</keyMaterial>"), key);
			return sb.ToString();
		}

		public string SetXmlProfile()
		{
			if (AvaliableWiFiList.Count == 0)
				return string.Empty;

			StringWriter sw = new StringWriter();
			XmlWriter xw = XmlWriter.Create(sw);
			xw.WriteStartDocument();
			xw.WriteStartElement("WLANProfile", @"http://www.microsoft.com/networking/WLAN/profile/v1");
			xw.WriteElementString("name", "MyNetwork");
			xw.WriteStartElement("SSIDConfig");
			xw.WriteStartElement("SSID");
			xw.WriteElementString("name", "MyNetworkSSID");
			xw.WriteEndElement();
			xw.WriteEndElement();
			xw.WriteElementString("connectionType", "ESS");
			xw.WriteStartElement("MSM");
			xw.WriteStartElement("security");
			xw.WriteStartElement("authEncryption");
			xw.WriteElementString("authentication", "open");
			xw.WriteElementString("encryption", "WEP");
			xw.WriteEndElement();
			xw.WriteStartElement("sharedKey");
			xw.WriteElementString("keyType", "networkKey");
			xw.WriteElementString("protected", "false");
			xw.WriteElementString("keyMaterial", "MyNetworkKey");
			xw.WriteEndElement();
			xw.WriteElementString("keyIndex", "0");
			xw.WriteEndElement();
			xw.WriteEndElement();
			xw.WriteEndElement();
			xw.WriteEndDocument();
			xw.Close();

			string profPtr = sw.ToString();
			sw.Close();
			WlanReasonCode reasonCode;
			int ret = WlanSetProfile(WlanHandle, AvaliableWiFiList[0].InterfaceGuid, WlanProfileFlags.AllUser, profPtr, null, true, IntPtr.Zero, out reasonCode);
			string msgError = WlanReasonCodeTostringApi((uint)ret);
			return profPtr;
		}

		public void GetProfileInfoList()
		{
			IntPtr ppProfileList = new IntPtr();
			if (AvaliableWiFiList.Count == 0)
				return;

			Guid pInterfaceGuid = AvaliableWiFiList[0].InterfaceGuid;
			uint error = WlanGetProfileList(WlanHandle, ref pInterfaceGuid, new IntPtr(), ref ppProfileList);
			string errorMsg = WlanReasonCodeTostringApi(error);
			WLAN_PROFILE_INFO_LIST wlanProfileInfoList = new WLAN_PROFILE_INFO_LIST(ppProfileList);
			WlanFreeMemory(ppProfileList);

		}

		public Dictionary<string, string> GetProfile()
		{
			if (AvaliableWiFiList.Count == 0)
				return new Dictionary<string, string>();

			Guid pInterfaceGuid = AvaliableWiFiList[0].InterfaceGuid;
			Dictionary<string, string> profilesConfig = new Dictionary<string, string>();
			//Profile list
			IntPtr ppProfileList = new IntPtr();
			uint result = WlanGetProfileList(WlanHandle, ref pInterfaceGuid, new IntPtr(), ref ppProfileList);
			string errorMsg = WlanReasonCodeTostringApi(result);

			WLAN_PROFILE_INFO_LIST wlanProfileInfoList = new WLAN_PROFILE_INFO_LIST(ppProfileList);
			WlanFreeMemory(ppProfileList);

			//Profile description
			uint pdwFlags = 0, pdwGrantedAccess = 0;
			for (int i = 0; i < wlanProfileInfoList.dwNumberOfItems; i++)
			{
				pdwFlags = 0;
				pdwGrantedAccess = 0;
				string strProfileName = wlanProfileInfoList.ProfileInfo[i].strProfileName;
				string pstrProfileXml = null;
				uint error = WlanGetProfile(WlanHandle, ref pInterfaceGuid, strProfileName, new IntPtr(), ref  pstrProfileXml,
											ref pdwFlags, ref pdwGrantedAccess);
				errorMsg = WlanReasonCodeTostringApi(error);

				if (!profilesConfig.ContainsKey(strProfileName))
					profilesConfig.Add(strProfileName, pstrProfileXml);
			}

			if (ppProfileList != IntPtr.Zero)
				Marshal.FreeHGlobal(ppProfileList);

			return profilesConfig;
		}

		public void WlanScan()
		{
			if (AvaliableWiFiList.Count == 0)
				return;

			Guid g;
			for (int i = 0; i < AvaliableWiFiList.Count; i++)
			{
				g = AvaliableWiFiList[i].InterfaceGuid;
				uint resultCode = WlanScan(WlanHandle, ref g, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

				string errorCode = WlanReasonCodeTostringApi(resultCode);
			}
		}

		/// <summary>
		/// Gets the profile's XML specification.
		/// </summary>
		/// <param name="profileName">The name of the profile.</param>
		/// <returns>The XML document.</returns>
		public string GetProfileXml(string profileName)
		{
			string profileXmlPtr = string.Empty;
			uint pdwFlags = 0;
			uint pdwGrantedAccess = 0;

			Guid pInterfaceGuid = AvaliableWiFiList[0].InterfaceGuid;
			uint errorCode = WlanGetProfile(WlanHandle, ref pInterfaceGuid, profileName, IntPtr.Zero, ref profileXmlPtr, ref pdwFlags,
											ref pdwGrantedAccess);

			string errorMsg = WlanReasonCodeTostringApi(errorCode);

			if (m_Win32Exc != null)
				throw m_Win32Exc;

			return profileXmlPtr;
		}

		public List<string> GetProfileXml()
		{
			if (AvaliableWiFiList.Count == 0)
				return null;

			Guid pInterfaceGuid = AvaliableWiFiList[0].InterfaceGuid;
			IntPtr ppProfileList = new IntPtr();
			uint result = WlanGetProfileList(WlanHandle, ref pInterfaceGuid, new IntPtr(), ref ppProfileList);
			if (result != ERROR_SUCCESS)
			{
				return null;
			}

			WLAN_PROFILE_INFO_LIST profileList = new WLAN_PROFILE_INFO_LIST(ppProfileList);
			List<string> profiles = new List<string>();

			for (int i = 0; i < profileList.dwNumberOfItems; i++)
			{
				string profileXmlPtr = string.Empty;
				uint pdwFlags = 0;
				uint pdwGrantedAccess = 0;
				string profileName = profileList.ProfileInfo[i].strProfileName;

				uint errorCode = WlanGetProfile(WlanHandle, ref pInterfaceGuid, profileName, IntPtr.Zero, ref profileXmlPtr, ref pdwFlags,
											ref pdwGrantedAccess);
				if (errorCode == ERROR_SUCCESS)
					profiles.Add(profileXmlPtr);
			}

			return profiles;
		}

		public void QureryStatus()
		{
			WLAN_HOSTED_NETWORK_STATUS status;
			ThrowIfError((int)WlanHostedNetworkQueryStatus(WlanHandle, out status, IntPtr.Zero));
		}

		public WLAN_HOSTED_NETWORK_REASON ForceStart()
		{
			WLAN_HOSTED_NETWORK_REASON failReason;
			CatchException((int)WlanHostedNetworkForceStart(WlanHandle, out failReason, IntPtr.Zero));
			if (m_Win32Exc != null)
				throw m_Win32Exc;

			this.m_HostedNetworkState = WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_active;

			return failReason;
		}

		public WLAN_HOSTED_NETWORK_REASON ForceStop()
		{
			WLAN_HOSTED_NETWORK_REASON failReason;
			CatchException((int)WlanHostedNetworkForceStop(WlanHandle, out failReason, IntPtr.Zero));
			if (m_Win32Exc != null)
				throw m_Win32Exc;

			this.m_HostedNetworkState = WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_idle;
			return failReason;
		}

		public WLAN_HOSTED_NETWORK_REASON StartUsing()
		{
			WLAN_HOSTED_NETWORK_REASON failReason;
			CatchException((int)WlanHostedNetworkStartUsing(WlanHandle, out failReason, IntPtr.Zero));
			if (m_Win32Exc != null)
				throw m_Win32Exc;

			this.m_HostedNetworkState = WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_active;
			return failReason;
		}

		public WLAN_HOSTED_NETWORK_REASON StopUsing()
		{
			WLAN_HOSTED_NETWORK_REASON failReason;
			CatchException((int)WlanHostedNetworkStopUsing(WlanHandle, out failReason, IntPtr.Zero));
			if (m_Win32Exc != null)
				throw m_Win32Exc;

			this.m_HostedNetworkState = WLAN_HOSTED_NETWORK_STATE.wlan_hosted_network_active;
			return failReason;
		}

		public WLAN_HOSTED_NETWORK_REASON InitSettings()
		{
			WLAN_HOSTED_NETWORK_REASON failReason;
			CatchException((int)WlanHostedNetworkInitSettings(WlanHandle, out failReason, IntPtr.Zero));
			if (m_Win32Exc != null)
				throw m_Win32Exc;

			return failReason;
		}

		public WLAN_HOSTED_NETWORK_REASON SetConnectionSettings(string hostedNetworkSSID, int maxNumberOfPeers)
		{
			WLAN_HOSTED_NETWORK_REASON failReason;

			WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS settings = new WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS();
			settings.hostedNetworkSSID = ConvertStringToDOT11_SSID(hostedNetworkSSID);
			settings.dwMaxNumberOfPeers = (uint)maxNumberOfPeers;

			IntPtr settingsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(settings));
			Marshal.StructureToPtr(settings, settingsPtr, false);

			ThrowIfError((int)WlanHostedNetworkSetProperty(this.WlanHandle, WLAN_HOSTED_NETWORK_OPCODE.wlan_hosted_network_opcode_connection_settings,
					(uint)Marshal.SizeOf(settings), settingsPtr, out failReason, IntPtr.Zero));

			return failReason;
		}

		public WLAN_HOSTED_NETWORK_REASON QuerySecondaryKey(out string passKey, out bool isPassPhrase, out bool isPersistent)
		{
			WLAN_HOSTED_NETWORK_REASON failReason;
			uint keyLen;
			CatchException((int)WlanHostedNetworkQuerySecondaryKey(WlanHandle, out keyLen, out passKey, out isPassPhrase, out isPersistent,
																	out failReason, IntPtr.Zero));
			if (m_Win32Exc != null)
				throw m_Win32Exc;

			return failReason;
		}

		public WLAN_HOSTED_NETWORK_REASON SetSecondaryKey(string passKey)
		{
			WLAN_HOSTED_NETWORK_REASON failReason;

			CatchException((int)WlanHostedNetworkSetSecondaryKey(WlanHandle, (uint)(passKey.Length + 1), passKey, true, true, out failReason, IntPtr.Zero));
			if (m_Win32Exc != null)
				throw m_Win32Exc;

			return failReason;
		}

		public WLAN_OPCODE_VALUE_TYPE QueryConnectionSettings(out string hostedNetworkSSID, out int maxNumberOfPeers)
		{
			uint dataSize;
			IntPtr dataPtr;
			WLAN_OPCODE_VALUE_TYPE opcode;

			CatchException((int)WlanHostedNetworkQueryProperty(WlanHandle, WLAN_HOSTED_NETWORK_OPCODE.wlan_hosted_network_opcode_connection_settings,
																out dataSize, out dataPtr, out opcode, IntPtr.Zero));
			if (m_Win32Exc != null)
				throw m_Win32Exc;

			var settings = (WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS)Marshal.PtrToStructure(dataPtr, typeof(WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS));
			hostedNetworkSSID = ConvertToString(settings.hostedNetworkSSID);
			maxNumberOfPeers = (int)settings.dwMaxNumberOfPeers;

			return opcode;
		}

		public void WlanGetFilters()
		{
			DOT11_NETWORK_LIST networkList;
			uint error = WlanGetFilterList(WlanHandle, WLAN_FILTER_LIST_TYPE.wlan_filter_list_type_user_permit, new IntPtr(),
											out networkList);
			if (error != ERROR_SUCCESS)
			{
				string messgae = WlanReasonCodeTostringApi(error);
			}
		}

		public void WlanEditProfileUI(IntPtr hwnd, string profileName)
		{
			if (AvaliableWiFiList.Count == 0)
				return;

			WlanReasonCode reasonCode;
			Guid guid = AvaliableWiFiList[0].InterfaceGuid;
			if (WlanUIEditProfile(this.WlanVersion, profileName, ref guid, hwnd, WL_DISPLAY_PAGES.WLConnectionPage,
							new IntPtr(), out reasonCode) != ERROR_SUCCESS)
			{
			}
		}

		private bool disposed = false;
		public void Dispose()
		{
			GC.SuppressFinalize(this);
			if (!disposed)
			{
				if (this.StationJoin != null)
					this.StationJoin = null;
				if (this.StationLeave != null)
					this.StationLeave = null;
				if (this.StationStateChange != null)
					this.StationStateChange = null;
				if (this.HostedNetworkStarted != null)
					this.HostedNetworkStarted = null;
				if (this.HostedNetworkStopped != null)
					this.HostedNetworkStopped = null;

				CloseWlanHandle();
				m_Win32Exc = null;
				AvaliableWiFiList.Clear();
				AvaliableWiFiList = null;
				if (ppInterfaceList != IntPtr.Zero)
					WlanFreeMemory(ppInterfaceList);
			}
		}

		internal static string ConvertToString(DOT11_MAC_ADDRESS mac)
		{
			var sb = new StringBuilder();

			sb.Append(ConvertToHexString(mac.one));
			sb.Append(":");
			sb.Append(ConvertToHexString(mac.two));
			sb.Append(":");
			sb.Append(ConvertToHexString(mac.three));
			sb.Append(":");
			sb.Append(ConvertToHexString(mac.four));
			sb.Append(":");
			sb.Append(ConvertToHexString(mac.five));
			sb.Append(":");
			sb.Append(ConvertToHexString(mac.six));

			return sb.ToString();
		}

		internal static string ConvertToString(DOT11_SSID ssid)
		{
			return ssid.ucSSID;
		}

		internal static string ConvertToHexString(byte value)
		{
			return Convert.ToString(value, 0x10).PadLeft(2, '0');
		}

		internal DOT11_SSID ConvertStringToDOT11_SSID(string ssid)
		{
			return new DOT11_SSID()
			{
				ucSSID = ssid,
				uSSIDLength = (uint)ssid.Length
			};
		}

		internal static void ThrowIfError(int win32ErrorCode)
		{
			if (win32ErrorCode != 0)
				throw new Win32Exception(win32ErrorCode);
		}

		private static Win32Exception m_Win32Exc;
		private static int m_ErrorCode;

		internal static void CatchException(int win32ErrorCode)
		{
			m_Win32Exc = null; m_ErrorCode = 0;
			if (win32ErrorCode != 0)
				m_Win32Exc = new Win32Exception(win32ErrorCode);
		}

		public static Win32Exception GetLastException()
		{
			return m_Win32Exc;
		}

		public enum WlanReasonCode
		{
			Success = 0,
			// general codes
			UNKNOWN = 0x10000 + 1,

			RANGE_SIZE = 0x10000,
			BASE = 0x10000 + RANGE_SIZE,

			// range for Auto Config
			//
			AC_BASE = 0x10000 + RANGE_SIZE,
			AC_CONNECT_BASE = (AC_BASE + RANGE_SIZE / 2),
			AC_END = (AC_BASE + RANGE_SIZE - 1),

			// range for profile manager
			// it has profile adding failure reason codes, but may not have 
			// connection reason codes
			//
			PROFILE_BASE = 0x10000 + (7 * RANGE_SIZE),
			PROFILE_CONNECT_BASE = (PROFILE_BASE + RANGE_SIZE / 2),
			PROFILE_END = (PROFILE_BASE + RANGE_SIZE - 1),

			// range for MSM
			//
			MSM_BASE = 0x10000 + (2 * RANGE_SIZE),
			MSM_CONNECT_BASE = (MSM_BASE + RANGE_SIZE / 2),
			MSM_END = (MSM_BASE + RANGE_SIZE - 1),

			// range for MSMSEC
			//
			MSMSEC_BASE = 0x10000 + (3 * RANGE_SIZE),
			MSMSEC_CONNECT_BASE = (MSMSEC_BASE + RANGE_SIZE / 2),
			MSMSEC_END = (MSMSEC_BASE + RANGE_SIZE - 1),

			// AC network incompatible reason codes
			//
			NETWORK_NOT_COMPATIBLE = (AC_BASE + 1),
			PROFILE_NOT_COMPATIBLE = (AC_BASE + 2),

			// AC connect reason code
			//
			NO_AUTO_CONNECTION = (AC_CONNECT_BASE + 1),
			NOT_VISIBLE = (AC_CONNECT_BASE + 2),
			GP_DENIED = (AC_CONNECT_BASE + 3),
			USER_DENIED = (AC_CONNECT_BASE + 4),
			BSS_TYPE_NOT_ALLOWED = (AC_CONNECT_BASE + 5),
			IN_FAILED_LIST = (AC_CONNECT_BASE + 6),
			IN_BLOCKED_LIST = (AC_CONNECT_BASE + 7),
			SSID_LIST_TOO_LONG = (AC_CONNECT_BASE + 8),
			CONNECT_CALL_FAIL = (AC_CONNECT_BASE + 9),
			SCAN_CALL_FAIL = (AC_CONNECT_BASE + 10),
			NETWORK_NOT_AVAILABLE = (AC_CONNECT_BASE + 11),
			PROFILE_CHANGED_OR_DELETED = (AC_CONNECT_BASE + 12),
			KEY_MISMATCH = (AC_CONNECT_BASE + 13),
			USER_NOT_RESPOND = (AC_CONNECT_BASE + 14),

			// Profile validation errors
			//
			INVALID_PROFILE_SCHEMA = (PROFILE_BASE + 1),
			PROFILE_MISSING = (PROFILE_BASE + 2),
			INVALID_PROFILE_NAME = (PROFILE_BASE + 3),
			INVALID_PROFILE_TYPE = (PROFILE_BASE + 4),
			INVALID_PHY_TYPE = (PROFILE_BASE + 5),
			MSM_SECURITY_MISSING = (PROFILE_BASE + 6),
			IHV_SECURITY_NOT_SUPPORTED = (PROFILE_BASE + 7),
			IHV_OUI_MISMATCH = (PROFILE_BASE + 8),
			// IHV OUI not present but there is IHV settings in profile
			IHV_OUI_MISSING = (PROFILE_BASE + 9),
			// IHV OUI is present but there is no IHV settings in profile
			IHV_SETTINGS_MISSING = (PROFILE_BASE + 10),
			// both/conflict MSMSec and IHV security settings exist in profile 
			CONFLICT_SECURITY = (PROFILE_BASE + 11),
			// no IHV or MSMSec security settings in profile
			SECURITY_MISSING = (PROFILE_BASE + 12),
			INVALID_BSS_TYPE = (PROFILE_BASE + 13),
			INVALID_ADHOC_CONNECTION_MODE = (PROFILE_BASE + 14),
			NON_BROADCAST_SET_FOR_ADHOC = (PROFILE_BASE + 15),
			AUTO_SWITCH_SET_FOR_ADHOC = (PROFILE_BASE + 16),
			AUTO_SWITCH_SET_FOR_MANUAL_CONNECTION = (PROFILE_BASE + 17),
			IHV_SECURITY_ONEX_MISSING = (PROFILE_BASE + 18),
			PROFILE_SSID_INVALID = (PROFILE_BASE + 19),
			TOO_MANY_SSID = (PROFILE_BASE + 20),

			// MSM network incompatible reasons
			//
			UNSUPPORTED_SECURITY_SET_BY_OS = (MSM_BASE + 1),
			UNSUPPORTED_SECURITY_SET = (MSM_BASE + 2),
			BSS_TYPE_UNMATCH = (MSM_BASE + 3),
			PHY_TYPE_UNMATCH = (MSM_BASE + 4),
			DATARATE_UNMATCH = (MSM_BASE + 5),

			// MSM connection failure reasons, to be defined
			// failure reason codes
			//
			// user called to disconnect
			USER_CANCELLED = (MSM_CONNECT_BASE + 1),
			// got disconnect while associating
			ASSOCIATION_FAILURE = (MSM_CONNECT_BASE + 2),
			// timeout for association
			ASSOCIATION_TIMEOUT = (MSM_CONNECT_BASE + 3),
			// pre-association security completed with failure
			PRE_SECURITY_FAILURE = (MSM_CONNECT_BASE + 4),
			// fail to start post-association security
			START_SECURITY_FAILURE = (MSM_CONNECT_BASE + 5),
			// post-association security completed with failure
			SECURITY_FAILURE = (MSM_CONNECT_BASE + 6),
			// security watchdog timeout
			SECURITY_TIMEOUT = (MSM_CONNECT_BASE + 7),
			// got disconnect from driver when roaming
			ROAMING_FAILURE = (MSM_CONNECT_BASE + 8),
			// failed to start security for roaming
			ROAMING_SECURITY_FAILURE = (MSM_CONNECT_BASE + 9),
			// failed to start security for adhoc-join
			ADHOC_SECURITY_FAILURE = (MSM_CONNECT_BASE + 10),
			// got disconnection from driver
			DRIVER_DISCONNECTED = (MSM_CONNECT_BASE + 11),
			// driver operation failed
			DRIVER_OPERATION_FAILURE = (MSM_CONNECT_BASE + 12),
			// Ihv service is not available
			IHV_NOT_AVAILABLE = (MSM_CONNECT_BASE + 13),
			// Response from ihv timed out
			IHV_NOT_RESPONDING = (MSM_CONNECT_BASE + 14),
			// Timed out waiting for driver to disconnect
			DISCONNECT_TIMEOUT = (MSM_CONNECT_BASE + 15),
			// An internal error prevented the operation from being completed.
			INTERNAL_FAILURE = (MSM_CONNECT_BASE + 16),
			// UI Request timed out.
			UI_REQUEST_TIMEOUT = (MSM_CONNECT_BASE + 17),
			// Roaming too often, post security is not completed after 5 times.
			TOO_MANY_SECURITY_ATTEMPTS = (MSM_CONNECT_BASE + 18),

			// MSMSEC reason codes
			//

			MSMSEC_MIN = MSMSEC_BASE,

			// Key index specified is not valid
			MSMSEC_PROFILE_INVALID_KEY_INDEX = (MSMSEC_BASE + 1),
			// Key required, PSK present
			MSMSEC_PROFILE_PSK_PRESENT = (MSMSEC_BASE + 2),
			// Invalid key length
			MSMSEC_PROFILE_KEY_LENGTH = (MSMSEC_BASE + 3),
			// Invalid PSK length
			MSMSEC_PROFILE_PSK_LENGTH = (MSMSEC_BASE + 4),
			// No auth/cipher specified
			MSMSEC_PROFILE_NO_AUTH_CIPHER_SPECIFIED = (MSMSEC_BASE + 5),
			// Too many auth/cipher specified
			MSMSEC_PROFILE_TOO_MANY_AUTH_CIPHER_SPECIFIED = (MSMSEC_BASE + 6),
			// Profile contains duplicate auth/cipher
			MSMSEC_PROFILE_DUPLICATE_AUTH_CIPHER = (MSMSEC_BASE + 7),
			// Profile raw data is invalid (1x or key data)
			MSMSEC_PROFILE_RAWDATA_INVALID = (MSMSEC_BASE + 8),
			// Invalid auth/cipher combination
			MSMSEC_PROFILE_INVALID_AUTH_CIPHER = (MSMSEC_BASE + 9),
			// 802.1x disabled when it's required to be enabled
			MSMSEC_PROFILE_ONEX_DISABLED = (MSMSEC_BASE + 10),
			// 802.1x enabled when it's required to be disabled
			MSMSEC_PROFILE_ONEX_ENABLED = (MSMSEC_BASE + 11),
			MSMSEC_PROFILE_INVALID_PMKCACHE_MODE = (MSMSEC_BASE + 12),
			MSMSEC_PROFILE_INVALID_PMKCACHE_SIZE = (MSMSEC_BASE + 13),
			MSMSEC_PROFILE_INVALID_PMKCACHE_TTL = (MSMSEC_BASE + 14),
			MSMSEC_PROFILE_INVALID_PREAUTH_MODE = (MSMSEC_BASE + 15),
			MSMSEC_PROFILE_INVALID_PREAUTH_THROTTLE = (MSMSEC_BASE + 16),
			// PreAuth enabled when PMK cache is disabled
			MSMSEC_PROFILE_PREAUTH_ONLY_ENABLED = (MSMSEC_BASE + 17),
			// Capability matching failed at network
			MSMSEC_CAPABILITY_NETWORK = (MSMSEC_BASE + 18),
			// Capability matching failed at NIC
			MSMSEC_CAPABILITY_NIC = (MSMSEC_BASE + 19),
			// Capability matching failed at profile
			MSMSEC_CAPABILITY_PROFILE = (MSMSEC_BASE + 20),
			// Network does not support specified discovery type
			MSMSEC_CAPABILITY_DISCOVERY = (MSMSEC_BASE + 21),
			// Passphrase contains invalid character
			MSMSEC_PROFILE_PASSPHRASE_CHAR = (MSMSEC_BASE + 22),
			// Key material contains invalid character
			MSMSEC_PROFILE_KEYMATERIAL_CHAR = (MSMSEC_BASE + 23),
			// Wrong key type specified for the auth/cipher pair
			MSMSEC_PROFILE_WRONG_KEYTYPE = (MSMSEC_BASE + 24),
			// "Mixed cell" suspected (AP not beaconing privacy, we have privacy enabled profile)
			MSMSEC_MIXED_CELL = (MSMSEC_BASE + 25),
			// Auth timers or number of timeouts in profile is incorrect
			MSMSEC_PROFILE_AUTH_TIMERS_INVALID = (MSMSEC_BASE + 26),
			// Group key update interval in profile is incorrect
			MSMSEC_PROFILE_INVALID_GKEY_INTV = (MSMSEC_BASE + 27),
			// "Transition network" suspected, trying legacy 802.11 security
			MSMSEC_TRANSITION_NETWORK = (MSMSEC_BASE + 28),
			// Key contains characters which do not map to ASCII
			MSMSEC_PROFILE_KEY_UNMAPPED_CHAR = (MSMSEC_BASE + 29),
			// Capability matching failed at profile (auth not found)
			MSMSEC_CAPABILITY_PROFILE_AUTH = (MSMSEC_BASE + 30),
			// Capability matching failed at profile (cipher not found)
			MSMSEC_CAPABILITY_PROFILE_CIPHER = (MSMSEC_BASE + 31),

			// Failed to queue UI request
			MSMSEC_UI_REQUEST_FAILURE = (MSMSEC_CONNECT_BASE + 1),
			// 802.1x authentication did not start within configured time 
			MSMSEC_AUTH_START_TIMEOUT = (MSMSEC_CONNECT_BASE + 2),
			// 802.1x authentication did not complete within configured time
			MSMSEC_AUTH_SUCCESS_TIMEOUT = (MSMSEC_CONNECT_BASE + 3),
			// Dynamic key exchange did not start within configured time
			MSMSEC_KEY_START_TIMEOUT = (MSMSEC_CONNECT_BASE + 4),
			// Dynamic key exchange did not succeed within configured time
			MSMSEC_KEY_SUCCESS_TIMEOUT = (MSMSEC_CONNECT_BASE + 5),
			// Message 3 of 4 way handshake has no key data (RSN/WPA)
			MSMSEC_M3_MISSING_KEY_DATA = (MSMSEC_CONNECT_BASE + 6),
			// Message 3 of 4 way handshake has no IE (RSN/WPA)
			MSMSEC_M3_MISSING_IE = (MSMSEC_CONNECT_BASE + 7),
			// Message 3 of 4 way handshake has no Group Key (RSN)
			MSMSEC_M3_MISSING_GRP_KEY = (MSMSEC_CONNECT_BASE + 8),
			// Matching security capabilities of IE in M3 failed (RSN/WPA)
			MSMSEC_PR_IE_MATCHING = (MSMSEC_CONNECT_BASE + 9),
			// Matching security capabilities of Secondary IE in M3 failed (RSN)
			MSMSEC_SEC_IE_MATCHING = (MSMSEC_CONNECT_BASE + 10),
			// Required a pairwise key but AP configured only group keys
			MSMSEC_NO_PAIRWISE_KEY = (MSMSEC_CONNECT_BASE + 11),
			// Message 1 of group key handshake has no key data (RSN/WPA)
			MSMSEC_G1_MISSING_KEY_DATA = (MSMSEC_CONNECT_BASE + 12),
			// Message 1 of group key handshake has no group key
			MSMSEC_G1_MISSING_GRP_KEY = (MSMSEC_CONNECT_BASE + 13),
			// AP reset secure bit after connection was secured
			MSMSEC_PEER_INDICATED_INSECURE = (MSMSEC_CONNECT_BASE + 14),
			// 802.1x indicated there is no authenticator but profile requires 802.1x
			MSMSEC_NO_AUTHENTICATOR = (MSMSEC_CONNECT_BASE + 15),
			// Plumbing settings to NIC failed
			MSMSEC_NIC_FAILURE = (MSMSEC_CONNECT_BASE + 16),
			// Operation was cancelled by caller
			MSMSEC_CANCELLED = (MSMSEC_CONNECT_BASE + 17),
			// Key was in incorrect format 
			MSMSEC_KEY_FORMAT = (MSMSEC_CONNECT_BASE + 18),
			// Security downgrade detected
			MSMSEC_DOWNGRADE_DETECTED = (MSMSEC_CONNECT_BASE + 19),
			// PSK mismatch suspected
			MSMSEC_PSK_MISMATCH_SUSPECTED = (MSMSEC_CONNECT_BASE + 20),
			// Forced failure because connection method was not secure
			MSMSEC_FORCED_FAILURE = (MSMSEC_CONNECT_BASE + 21),
			// ui request couldn't be queued or user pressed cancel
			MSMSEC_SECURITY_UI_FAILURE = (MSMSEC_CONNECT_BASE + 22),

			MSMSEC_MAX = MSMSEC_END
		}
	}

}
